diff -Nru a/Documentation/Changes b/Documentation/Changes --- a/Documentation/Changes Sun Jun 2 18:44:58 2002 +++ b/Documentation/Changes Sun Jun 2 18:44:58 2002 @@ -77,13 +77,11 @@ have not received much testing for Linux kernel compilation, and there are almost certainly bugs (mainly, but not exclusively, in the kernel) that will need to be fixed in order to use these compilers. In any case, using -pgcc instead of egcs or plain gcc is just asking for trouble. +pgcc instead of plain gcc is just asking for trouble. -Note that gcc 2.7.2.3 is no longer a supported kernel compiler. The kernel -no longer works around bugs in gcc 2.7.2.3 and, in fact, will refuse to -be compiled with it. egcs-1.1.2 has register allocation problems in very -obscure cases. We have ensured the kernel does not trip these in any known -situation. The 2.5 tree is likely to drop egcs-1.1.2 workarounds. +Note that gcc 2.7.2.3 and gcc 2.91.66 (egcs-1.1.2) are no longer supported +kernel compilers. The kernel no longer works around bugs in these versions, +and, in fact, will refuse to be compiled with it. The Red Hat gcc 2.96 compiler subtree can also be used to build this tree. You should ensure you use gcc-2.96-74 or later. gcc-2.96-54 will not build @@ -274,10 +272,6 @@ Kernel compilation ****************** - -egcs 1.1.2 (gcc 2.91.66) ------------------------- -o gcc 2.95.3 ---------- diff -Nru a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile --- a/Documentation/DocBook/Makefile Sun Jun 2 18:44:57 2002 +++ b/Documentation/DocBook/Makefile Sun Jun 2 18:44:57 2002 @@ -113,6 +113,9 @@ $(TOPDIR)/drivers/net/wan/syncppp.c \ $(TOPDIR)/drivers/net/wan/z85230.c \ $(TOPDIR)/drivers/usb/core/hcd.c \ + $(TOPDIR)/drivers/usb/core/urb.c \ + $(TOPDIR)/drivers/usb/core/message.c \ + $(TOPDIR)/drivers/usb/core/config.c \ $(TOPDIR)/drivers/usb/core/usb.c \ $(TOPDIR)/drivers/video/fbmem.c \ $(TOPDIR)/drivers/video/fbcmap.c \ diff -Nru a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl --- a/Documentation/DocBook/kernel-api.tmpl Sun Jun 2 18:44:56 2002 +++ b/Documentation/DocBook/kernel-api.tmpl Sun Jun 2 18:44:56 2002 @@ -282,6 +282,9 @@ USB Core APIs +!Edrivers/usb/core/urb.c +!Edrivers/usb/core/config.c +!Edrivers/usb/core/message.c !Edrivers/usb/core/usb.c diff -Nru a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking --- a/Documentation/filesystems/Locking Sun Jun 2 18:44:57 2002 +++ b/Documentation/filesystems/Locking Sun Jun 2 18:44:57 2002 @@ -138,7 +138,7 @@ int (*prepare_write)(struct file *, struct page *, unsigned, unsigned); int (*commit_write)(struct file *, struct page *, unsigned, unsigned); int (*bmap)(struct address_space *, long); - int (*flushpage) (struct page *, unsigned long); + int (*invalidatepage) (struct page *, unsigned long); int (*releasepage) (struct page *, int); int (*direct_IO)(int, struct inode *, struct kiobuf *, unsigned long, int); @@ -156,7 +156,7 @@ prepare_write: no yes commit_write: no yes bmap: yes -flushpage: no yes +invalidatepage: no yes releasepage: no yes ->prepare_write(), ->commit_write(), ->sync_page() and ->readpage() @@ -206,10 +206,10 @@ instances do not actually need the BKL. Please, keep it that way and don't breed new callers. - ->flushpage() is called when the filesystem must attempt to drop + ->invalidatepage() is called when the filesystem must attempt to drop some or all of the buffers from the page when it is being truncated. It -returns zero on success. If ->flushpage is zero, the kernel uses -block_flushpage() instead. +returns zero on success. If ->invalidatepage is zero, the kernel uses +block_invalidatepage() instead. ->releasepage() is called when the kernel is about to try to drop the buffers from the page in preparation for freeing it. It returns zero to diff -Nru a/Documentation/networking/e100.txt b/Documentation/networking/e100.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/networking/e100.txt Sun Jun 2 18:44:58 2002 @@ -0,0 +1,272 @@ +Linux* Base Driver for the Intel(R) PRO/100 Family of Adapters +============================================================== + +April 9, 2002 + + +Contents +======== + +- In This Release +- Supported Adapters +- Command Line Parameters +- CPU Cycle Saver +- Additional Configurations +- Support + + +In This Release +=============== + +This file describes the Linux* Base Driver for the Intel(R) PRO/100 Family of +Adapters, version 2.0.x. This driver includes support for Itanium(TM)-based +systems. + +New for this release: + + - Additional ethtool functionality, including link status test and EEPROM + read/write. A third-party application can use the ethtool interface to + get and set driver parameters. + + - Support for Zero copy on 82550-based adapters. This feature provides + faster data throughput and significant CPU usage improvement in systems + that use the relevant system call (sendfile(2)). + + - Support for large MTU-enabling interface (1504 bytes) with kernel's + VLAN module + + - Support for polling on RX + + - Support for Wake On LAN* on 82550 and 82559-based adapters + + +Supported Adapters +================== + +The following Intel network adapters are compatible with the drivers +in this release: + +Controller Adapter Name Board IDs +---------- ------------ --------- + +82558 PRO/100+ PCI Adapter 668081-xxx, 689661-xxx + +82558 PRO/100+ Management Adapter 691334-xxx, 701738-xxx, + 721383-xxx + +82558 PRO/100+ Dual Port Server Adapter 714303-xxx, 711269-xxx, + A28276-xxx + +82558 PRO/100+ PCI Server Adapter 710550-xxx + +82550 PRO/100 S Server Adapter 752438-xxx (82550) +82559 A56831-xxx, A10563-xxx, + A12171-xxx, A12321-xxx, + A12320-xxx, A12170-xxx + 748568-xxx (82559) + 748565-xxx (82559) + + +82550 PRO/100 S Desktop Adapter 751767-xxx (82550) +82559 748592-xxx, A12167-xxx, + A12318-xxx, A12317-xxx, + A12165-xxx + 748569-xxx (82559) + + + +82559 PRO/100+ Server Adapter 729757-xxx + +82559 PRO/100 S Management Adapter 748566-xxx, 748564-xxx + +82550 PRO/100 S Dual Port Server Adapter A56831-xxx + +82551 PRO/100 M Desktop Adapter A80897-xxx + + PRO/100 S Advanced Management Adapter 747842-xxx, 745171-xxx + +CNR PRO/100 VE Desktop Adapter A10386-xxx, A10725-xxx, + A23801-xxx, A19716-xxx + + + PRO/100 VM Desktop Adapter A14323-xxx, A19725-xxx, + A23801-xxx, A22220-xxx, + A23796-xxx + + +To verify that your adapter is supported, find the board ID number on the +adapter. Look for a label that has a barcode and a number in the format +123456-001 (six digits hyphen three digits). Match this to the list of +numbers above. + +For more information on how to identify your adapter, go to the Adapter & +Driver ID Guide at: + + http://support.intel.com/support/network/adapter/pro100/21397.htm + +For the latest Intel PRO/100 network driver for Linux, see: + + http://appsr.intel.com/scripts-df/support_intel.asp + + +Command Line Parameters +======================= + +The following parameters are used by entering them on the command line with +the modprobe or insmod command. For example, with two Intel PRO/100 PCI +adapters, entering: + + modprobe e100 TxDescriptors=32,128 + +loads the e100 driver with 32 TX resources for the first adapter and 128 TX +resources for the second adapter. This configuration favors the second +adapter. The driver supports up to 16 network adapters concurrently. + +NOTE: Giving any command line option the value "-1" causes the driver to use + the appropriate default value for that option, as if no value was + specified. + + +BundleMax +Valid Range: 0x1-0xFFFF +Default Value: 6 + This parameter holds the maximum number of packets in a bundle. Suggested + values range from 2 to 10. See "CPU Cycle Saver." + +BundleSmallFr +Valid Range: 0-1 (0=off, 1=on) +Default Value: 0 + The value 1 (on) causes small packets (less than 128 bytes) to be bundled. + See "CPU Cycle Saver." + +e100_speed_duplex +Valid Range: 0-4 (1=10half;2=10full;3=100half;4=100full) +Default Value: 0 + The default value of 0 is set to auto-negotiate if the link partner is set + to auto-negotiate. If the link partner is forced, e100_speed_duplex + defaults to half-duplex. + Example usage: insmod e100.o e100_speed_duplex=4,4 (for two adapters) + +flow_control +Valid Range: 0-1 (0=off, 1=on) +Default Value: 0 + This parameter controls the automatic generation(Tx) and response(Rx) to + Ethernet PAUSE frames. flow_control should NOT be set to 1 when the e100 + adapter is connected to an interface that does not support Ethernet PAUSE + frames and when the e100_speed_duplex parameter is NOT set to zero. + +IntDelay +Valid Range: 0-0xFFFF (0=off) +Default Value: 1536 + This parameter holds the number of time units (in adapter terminology) + until the adapter generates an interrupt. The recommended value for + IntDelay is 0x600 (upon initialization). Suggested values range from + 0x200h to 0x800. See "CPU Cycle Saver." + +IFS +Valid Range: 0-1 (0=off, 1=on) +Default Value: 1 + Inter Frame Spacing (IFS) aims to reduce the number of Ethernet frame + collisions by altering the time between frame transmissions. When IFS is + enabled the driver tries to find an optimal IFS value. However, some + switches function better when IFS is disabled. + +PollingMaxWork +Valid Range: 1-1024 (max number of RxDescriptors) +Default Value: Specified number of RxDescriptors + This value specifies the maximum number of receive packets that are + processed on a single polling call. This parameter is invalid if + RxCongestionControl is set to 0. + +RxCongestionControl +Valid Range: 0-1 (0=off, 1=on) +Default Value: 1 + 1 enables polling mode. When the link is congested, the driver can decide + to handle received packets by polling them, instead of waiting until + interrupts occur. + +RxDescriptors +Valid Range: 8-1024 +Default Value: 64 + This parameter defines the number of receive descriptors allocated by + the driver. Increasing this value allows the driver to buffer more + incoming packets before the driver is required to service an interrupt. + The maximum value for Itanium-based systems is 64. + +TxDescriptors +Valid Range: 19-1024 +Default Value: 64 + This value is the number of transmit descriptors allocated by the driver. + Increasing this value allows the protocol stack to queue more transmits at + the driver level. The maximum value for Itanium-based systems is 64. + +ucode (not available for 82557-based adapters) +Valid Range: 0-1 (0=off, 1=on) +Default Value: 0 for 82558-based adapters + 1 for 82559(and higher)-based adapters + On uploads the micro code to the adapter, which enables CPU Cycle Saver. + See the section "CPU Cycle Saver" below. + Example usage: insmod e100.o ucode=0 (does not reduce CPU usage) + +XsumRX +Valid Range: 0-1 (0=off, 1=on) +Default Value: 1 + On allows Rx checksum offloading for TCP/UDP packets. Requires that the + hardware support this feature. + + +CPU Cycle Saver +================ + +CPU Cycle Saver reduces CPU utilization by reducing the number of interrupts +that the adapter generates. + +When CPU Cycle Saver is turned off, the adapter generates one interrupt for +every frame that is received. This means that the operating system stops what +it is doing and switches to the network driver in order to process the +receive. + +When CPU Cycle Saver is on, the adapter does not generate an interrupt for +every frame it receives. Instead, it waits until it receives several frames +before generating an interrupt. This reduces the amount of time spent +switching to and from the driver. + +CPU Cycle Saver consists of these arguments: IntDelay, BundleMax and +BundleSmallFr. When IntDelay is increased, the adapter waits longer for +frames to arrive before generating the interrupt. By increasing BundleMax, +the network adapter waits for the number of frames specified to arrive before +generating the interrupt. When BundleSmallFr is disabled, the adapter does +not bundle packets that are smaller than 128 bytes. Such small packets are +often, but not always, control packets that are better served immediately. + +For most users, it is recommended that CPU Cycle Saver be used with the +default values specified in the Command Line Parameters section. However, in +some cases, performance problems may occur with CPU Cycle Saver. If such +problems are observed, we recommend turning off this feature by setting +ucode=0. + + +Support +======= + +For general information and support, go to the Intel support website at: + + http://support.intel.com + +If an issue is identified with the released source code on the supported +kernel with a supported adapter, email the specific information related to +the issue to linux.nics@intel.com. + + +License +======= + +This software program is released under the terms of a license agreement +between you ('Licensee') and Intel. Do not use or load this software or any +associated materials (collectively, the 'Software') until you have carefully +read the full terms and conditions of the LICENSE located in this software +package. By loading or using the Software, you agree to the terms of this +Agreement. If you do not agree with the terms of this Agreement, do not +install or use the Software. + +* Other names and brands may be claimed as the property of others. diff -Nru a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt --- a/Documentation/networking/e1000.txt Sun Jun 2 18:44:57 2002 +++ b/Documentation/networking/e1000.txt Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters =============================================================== -February 5, 2002 +April 23, 2002 Contents @@ -11,6 +11,7 @@ - Supported Adapters - Command Line Parameters - Speed and Duplex Configuration +- Additional Configurations - Known Issues - Support @@ -19,17 +20,27 @@ =============== This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family -of Adapters, version 4.2.x. -This driver includes support for Itanium(TM)-based systems. +of Adapters, version 4.2.x. This driver includes support for +Itanium(TM)-based systems. This release version includes the following: - - support for the ethtool 1.4 interface. A third-party application can use + - Support for the ethtool 1.5 interface. A third-party application can use the ethtool interface to get and set driver parameters. - - the zero copy feature. Zero copy provides faster information throughput. - By default, this feature is enabled if using a kernel that supports it. - Zero copy is not supported on the original PWLA8490 (plain) adapter. + - Zero copy. This feature provides faster data throughput. Enabled by + default in supporting kernels. It is not supported on the Intel(R) + PRO/1000 Gigabit Server Adapter. + +New features include: + + - Support for the 82545 and 82546-based adapters listed below + + - Wake on LAN* support via ethtool for 82540, 82544, 82545, and 82546- + based adapters + + - Adaptive IFS for increased performance at half duplex + Supported Adapters @@ -38,21 +49,32 @@ The following Intel network adapters are compatible with the drivers in this release: - Controller Adapter Name Board IDs - ---------- ------------ --------- + Controller Adapter Name Board IDs + ---------- ------------ --------- + + 82542 PRO/1000 Gigabit Server Adapter 700262-xxx, 717037-xxx + + 82543 PRO/1000 F Server Adapter 738640-xxx, A38888-xxx + + 82543 PRO/1000 T Server Adapter A19845-xxx, A33948-xxx + + 82544 PRO/1000 XT Server Adapter A51580-xxx + + 82544 PRO/1000 XF Server Adapter A50484-xxx - 82542 PRO/1000 Gigabit Server Adapter 700262-xxx, 717037-xxx + 82544 PRO/1000 T Desktop Adapter A62947-xxx - 82543 PRO/1000 F Server Adapter 738640-xxx, A38888-xxx, - A06512-xxx + 82540 PRO/1000 MT Desktop Adapter A78408-xxx - 82543 PRO/1000 T Server Adapter A19845-xxx, A33948-xxx + 82545 PRO/1000 MT Server Adapter A92165-xxx - 82544 PRO/1000 XT Server Adapter A51580-xxx + 82546 PRO/1000 MT Dual Port Server Adapter A92111-xxx - 82544 PRO/1000 XF Server Adapter A50484-xxx + 82545 PRO/1000 MF Server Adapter A91622-xxx - 82544 PRO/1000 T Desktop Adapter A62947-xxx + 82545 PRO/1000 MF Server Adapter(LX) A91624-xxx + + 82546 PRO/1000 MF Dual Port Server Adapter A91620-xxx To verify your Intel adapter is supported, find the board ID number on the @@ -73,8 +95,8 @@ Command Line Parameters ======================= -If the driver is built as a module, the following parameters are used by -entering them on the command line with the modprobe or insmod command. +If the driver is built as a module, the following parameters are used by +entering them on the command line with the modprobe or insmod command. For example, with two PRO/1000 PCI adapters, entering: insmod e1000 TxDescriptors=80,128 @@ -86,14 +108,14 @@ "Speed and Duplex Configuration" section in this document. -AutoNeg (Intel PRO/1000 T and PRO/1000 XT server adapters only) -Valid Range: 0-0x0F, 0x20-0x2F +AutoNeg (adapters using copper connections only) +Valid Range: 0x01-0x0F, 0x20-0x2F Default Value: 0x2F This parameter is a bit mask that specifies which speed and duplex settings the board advertises. When this parameter is used, the Speed and Duplex parameters must not be specified. -Duplex (Intel PRO/1000 T and PRO/1000 XT server adapters only) +Duplex (adapters using copper connections only) Valid Range: 0-2 (0=auto-negotiate, 1=half, 2=full) Default Value: 0 Defines the direction in which data is allowed to flow. Can by either one @@ -109,26 +131,27 @@ RxDescriptors Valid Range: 80-256 for 82542 and 82543-based adapters - 80-4096 for 82544-based adapters -Default Value: 256 + 80-4096 for 82540, 82544, 82545, and 82546-based adapters +Default Value: 80 This value is the number of receive descriptors allocated by the driver. Increasing this value allows the driver to buffer more incoming packets. Each descriptor is 16 bytes. A receive buffer is also allocated for each descriptor and can be either 2048, 4096, 8192, or 16384 bytes, depending - on the MTU setting. + on the MTU setting. The maximum MTU size is 16110. RxIntDelay Valid Range: 0-65535 (0=off) -Default Value: 64 +Default Value: 64 (82542, 82543, and 82544-based adapters) + 128 (82540, 82545, and 82546-based adapters) This value delays the generation of receive interrupts in units of 1.024 microseconds. Receive interrupt reduction can improve CPU efficiency if properly tuned for specific network traffic. Increasing this value adds extra latency to frame reception and can end up decreasing the throughput - of TCP traffic. If the system is reporting dropped receives, this value + of TCP traffic. If the system is reporting dropped receives, this value may be set too high, causing the driver to run out of available receive descriptors. -Speed (Intel PRO/1000 T and PRO/1000 XT server adapters only) +Speed (adapters using copper connections only) Valid Settings: 0, 10, 100, 1000 Default Value: 0 (auto-negotiate at all supported speeds) Speed forces the line speed to the specified value in megabits per second @@ -138,21 +161,12 @@ TxDescriptors Valid Range: 80-256 for 82542 and 82543-based adapters - 80-4096 for 82544-based adapters + 80-4096 for 82540, 82544, 82545, and 82546-based adapters Default Value: 256 This value is the number of transmit descriptors allocated by the driver. Increasing this value allows the driver to queue more transmits. Each descriptor is 16 bytes. -TxIntDelay -Valid Range: 0-65535 (0=off) -Default Value: 64 - This value delays the generation of transmit interrupts in units of 1.024 - microseconds. Transmit interrupt reduction can improve CPU efficiency if - properly tuned for specific network traffic. If the system is reporting - dropped transmits, this value may be set too high causing the driver to - run out of available transmit descriptors. - XsumRX (not available on the PRO/1000 Gigabit Server Adapter) Valid Range: 0-1 Default Value: 1 @@ -163,9 +177,8 @@ Speed and Duplex Configuration ============================== -Three keywords are used to control the speed and duplex configuration of the -PRO/1000 T and PRO/1000 XT server adapters. These keywords are Speed, Duplex, -and AutoNeg. +Three keywords are used to control the speed and duplex configuration. These +keywords are Speed, Duplex, and AutoNeg. If the board uses a fiber interface, these keywords are ignored, and the fiber interface board only links at 1000 Mbps full-duplex. @@ -199,16 +212,32 @@ adapter MUST be forced to the same speed/duplex. +Additional Configurations +========================= + + Jumbo Frames + ------------ + + The driver supports Jumbo Frames for all adapters except 82542-based + adapters. Jumbo Frames support is enabled by changing the MTU to a value + larger than the default of 1500. Use the ifconfig command to increase the + MTU size. For example: + + ifconfig ethx mtu 9000 up + + Known Issues ============ - Driver Hangs Under Heavy Traffic Loads - -------------------------------------- + Inconsistent Driver Behavior Under Heavy Traffic Loads + ------------------------------------------------------ - Intel is aware that previously released e1000 drivers may hang under very - specific types of heavy traffic loads. This version includes a workaround - that resets the adapter automatically if a hang condition is detected. This - workaround ensures network traffic flow is not affected when a hang occurs. + Adapters based on the Intel 82543 and 82544 LAN controllers may hang (stop + transmitting) under certain network conditions. If this occurs a message + is logged in the system event log. In addition, the controller is + automatically reset, restoring the network connection. To eliminate the + potential for the hang change the RxIntDelay parameter to zero. For details + on the RxIntDelay parameter see the Command Line Parameters section. Jumbo Frames System Requirement ------------------------------- diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Sun Jun 2 18:44:56 2002 +++ b/MAINTAINERS Sun Jun 2 18:44:56 2002 @@ -795,6 +795,11 @@ M: tigran@veritas.com S: Maintained +INTEL PRO/100 ETHERNET SUPPORT +P: Scott Feldman +M: scott.feldman@intel.com +S: Supported + INTEL PRO/1000 GIGABIT ETHERNET SUPPORT P: Chris Leech M: christopher.leech@intel.com diff -Nru a/Makefile b/Makefile --- a/Makefile Sun Jun 2 18:44:56 2002 +++ b/Makefile Sun Jun 2 18:44:56 2002 @@ -1,8 +1,24 @@ VERSION = 2 PATCHLEVEL = 5 -SUBLEVEL = 19 +SUBLEVEL = 20 EXTRAVERSION = +# We are using a recursive build, so we need to do a little thinking +# to get the ordering right. +# +# Most importantly: sub-Makefiles should only ever modify files in +# their own directory. If in some directory we have a dependency on +# a file in another dir (which doesn't happen often, but it's of +# unavoidable when linking the built-in.o targets which finally +# turn into vmlinux), we will call a sub make in that other dir, and +# after that we are sure that everything which is in that other dir +# is now up to date. +# +# The only cases where we need to modify files which have global +# effects are thus separated out and done before the recursive +# descending is started. They are now explicitly listed as the +# prepare rule. + KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -62,13 +78,8 @@ ifeq (.config,$(wildcard .config)) include .config -ifeq (.hdepend,$(wildcard .hdepend)) do-it-all: vmlinux else -CONFIGURATION = depend -do-it-all: depend -endif -else CONFIGURATION = config do-it-all: config endif @@ -172,9 +183,16 @@ # Handle descending into subdirectories listed in $(SUBDIRS) .PHONY: $(SUBDIRS) -$(SUBDIRS): FORCE include/linux/version.h include/config/MARKER +$(SUBDIRS): prepare @$(MAKE) -C $@ +# Things we need done before we even start the actual build. +# The dependency on .hdepend will in turn take care of +# include/asm, include/linux/version etc. + +.PHONY: prepare +prepare: .hdepend include/config/MARKER + # Single targets # --------------------------------------------------------------------------- @@ -189,69 +207,70 @@ %.o: %.S FORCE @$(MAKE) -C $(@D) $(@F) -# Configuration -# --------------------------------------------------------------------------- - -oldconfig: symlinks - $(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in +# FIXME: The asm symlink changes when $(ARCH) changes. That's +# hard to detect, but I suppose "make mrproper" is a good idea +# before switching between archs anyway. + +include/asm: + @echo 'Making asm->asm-$(ARCH) symlink' + @ln -s asm-$(ARCH) $@ + @echo 'Making directory include/linux/modules' + @mkdir include/linux/modules -xconfig: symlinks - @$(MAKE) -C scripts kconfig.tk - wish -f scripts/kconfig.tk - -menuconfig: include/linux/version.h symlinks - @$(MAKE) -C scripts/lxdialog all - $(CONFIG_SHELL) scripts/Menuconfig arch/$(ARCH)/config.in - -config: symlinks - $(CONFIG_SHELL) scripts/Configure arch/$(ARCH)/config.in - -# make asm->asm-$(ARCH) symlink - -symlinks: - rm -f include/asm - ( cd include ; ln -sf asm-$(ARCH) asm) - @if [ ! -d include/linux/modules ]; then \ - mkdir include/linux/modules; \ - fi - -# split autoconf.h into include/linux/config/* +# Split autoconf.h into include/linux/config/* include/config/MARKER: scripts/split-include include/linux/autoconf.h scripts/split-include include/linux/autoconf.h include/config @ touch include/config/MARKER # Generate some files +# --------------------------------------------------------------------------- -$(TOPDIR)/include/linux/version.h: include/linux/version.h +# version.h changes when $(KERNELRELEASE) etc change, as defined in +# this Makefile -include/linux/version.h: ./Makefile +include/linux/version.h: Makefile @echo Generating $@ @. scripts/mkversion_h $@ $(KERNELRELEASE) $(VERSION) $(PATCHLEVEL) $(SUBLEVEL) -# helpers built in scripts/ +# Helpers built in scripts/ +# --------------------------------------------------------------------------- scripts/mkdep scripts/split-include : FORCE @$(MAKE) -C scripts -# --------------------------------------------------------------------------- # Generate dependencies +# --------------------------------------------------------------------------- -depend dep: dep-files +# In the same pass, generate module versions, that's why it's +# all mixed up here. -dep-files: scripts/mkdep archdep include/linux/version.h - scripts/mkdep -- `find $(FINDHPATH) -name SCCS -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend +.PHONY: depend dep $(patsubst %,_sfdep_%,$(SUBDIRS)) + +depend dep: .hdepend + +# .hdepend is missing prerequisites - in fact dependencies need +# to be redone basically each time anything changed - since +# that's too expensive, we traditionally rely on the user to +# run "make dep" manually whenever necessary. In this case, +# we make "FORCE" a prequisite, to force redoing the +# dependencies. Yeah, that's ugly, and it'll go away soon. + +.hdepend: scripts/mkdep include/linux/version.h include/asm \ + $(if $(filter dep depend,$(MAKECMDGOALS)),FORCE) + scripts/mkdep -- `find $(FINDHPATH) -name SCCS -prune -o -follow -name \*.h ! -name modversions.h -print` > $@ @$(MAKE) $(patsubst %,_sfdep_%,$(SUBDIRS)) ifdef CONFIG_MODVERSIONS - $(MAKE) update-modverfile + @$(MAKE) include/linux/modversions.h endif + @$(MAKE) archdep -.PHONY: $(patsubst %,_sfdep_%,$(SUBDIRS)) $(patsubst %,_sfdep_%,$(SUBDIRS)): FORCE @$(MAKE) -C $(patsubst _sfdep_%, %, $@) fastdep -# update modversions.h, but only if it would change -update-modverfile: +# Update modversions.h, but only if it would change. + +include/linux/modversions.h: FORCE @(echo "#ifndef _LINUX_MODVERSIONS_H";\ echo "#define _LINUX_MODVERSIONS_H"; \ echo "#include "; \ @@ -260,13 +279,13 @@ if [ -f $$f ]; then echo "#include "; fi; \ done; \ echo "#endif"; \ - ) > $(TOPDIR)/include/linux/modversions.h.tmp - @if [ -r $(TOPDIR)/include/linux/modversions.h ] && cmp -s $(TOPDIR)/include/linux/modversions.h $(TOPDIR)/include/linux/modversions.h.tmp; then \ - echo $(TOPDIR)/include/linux/modversions.h was not updated; \ - rm -f $(TOPDIR)/include/linux/modversions.h.tmp; \ + ) > $@.tmp + @if [ -r $@ ] && cmp -s $@ $@.tmp; then \ + echo $@ was not updated; \ + rm -f $@.tmp; \ else \ - echo $(TOPDIR)/include/linux/modversions.h was updated; \ - mv -f $(TOPDIR)/include/linux/modversions.h.tmp $(TOPDIR)/include/linux/modversions.h; \ + echo $@ was updated; \ + mv -f $@.tmp $@; \ fi # --------------------------------------------------------------------------- @@ -277,7 +296,7 @@ # Build modules ifdef CONFIG_MODVERSIONS -MODFLAGS += -DMODVERSIONS -include $(HPATH)/linux/modversions.h +MODFLAGS += -include $(HPATH)/linux/modversions.h endif .PHONY: modules @@ -332,6 +351,90 @@ endif # CONFIG_MODULES +# Scripts to check various things for consistency +# --------------------------------------------------------------------------- + +checkconfig: + find * -name '*.[hcS]' -type f -print | sort | xargs $(PERL) -w scripts/checkconfig.pl + +checkhelp: + find * -name [cC]onfig.in -print | sort | xargs $(PERL) -w scripts/checkhelp.pl + +checkincludes: + find * -name '*.[hcS]' -type f -print | sort | xargs $(PERL) -w scripts/checkincludes.pl + +# Generate tags for editors +# --------------------------------------------------------------------------- + +TAGS: FORCE + { find include/asm-${ARCH} -name '*.h' -print ; \ + find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print ; \ + find $(SUBDIRS) init -name '*.[ch]' ; } | grep -v SCCS | etags - + +# Exuberant ctags works better with -I +tags: FORCE + CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \ + ctags $$CTAGSF `find include/asm-$(ARCH) -name '*.h'` && \ + find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs ctags $$CTAGSF -a && \ + find $(SUBDIRS) init -name '*.[ch]' | xargs ctags $$CTAGSF -a + +# Assorted miscellaneous targets +# --------------------------------------------------------------------------- + +# Documentation targets + +sgmldocs psdocs pdfdocs htmldocs: + @$(MAKE) -C Documentation/DocBook $@ + + +# RPM target +# +# If you do a make spec before packing the tarball you can rpm -ta it + +spec: + . scripts/mkspec >kernel.spec + +# Build a tar ball, generate an rpm from it and pack the result +# There arw two bits of magic here +# 1) The use of /. to avoid tar packing just the symlink +# 2) Removing the .dep files as they have source paths in them that +# will become invalid + +rpm: clean spec + find . \( -size 0 -o -name .depend -o -name .hdepend \) -type f -print | xargs rm -f + set -e; \ + cd $(TOPDIR)/.. ; \ + ln -sf $(TOPDIR) $(KERNELPATH) ; \ + tar -cvz --exclude CVS -f $(KERNELPATH).tar.gz $(KERNELPATH)/. ; \ + rm $(KERNELPATH) ; \ + cd $(TOPDIR) ; \ + . scripts/mkversion > .version ; \ + rpm -ta $(TOPDIR)/../$(KERNELPATH).tar.gz ; \ + rm $(TOPDIR)/../$(KERNELPATH).tar.gz + +# Targets which don't need .config +# =========================================================================== + +# Kernel configuration +# --------------------------------------------------------------------------- + +.PHONY: oldconfig xconfig menuconfig config + +oldconfig: + $(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in + +xconfig: + @$(MAKE) -C scripts kconfig.tk + wish -f scripts/kconfig.tk + +menuconfig: + @$(MAKE) -C scripts/lxdialog all + $(CONFIG_SHELL) scripts/Menuconfig arch/$(ARCH)/config.in + +config: + $(CONFIG_SHELL) scripts/Configure arch/$(ARCH)/config.in + + # Cleaning up # --------------------------------------------------------------------------- @@ -409,80 +512,19 @@ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -type f -print` TAGS tags -# Assorted miscellaneous targets -# --------------------------------------------------------------------------- - -# Documentation targets - -sgmldocs psdocs pdfdocs htmldocs: - @$(MAKE) -C Documentation/DocBook $@ - - -# RPM target -# -# If you do a make spec before packing the tarball you can rpm -ta it - -spec: - . scripts/mkspec >kernel.spec - -# Build a tar ball, generate an rpm from it and pack the result -# There arw two bits of magic here -# 1) The use of /. to avoid tar packing just the symlink -# 2) Removing the .dep files as they have source paths in them that -# will become invalid - -rpm: clean spec - find . \( -size 0 -o -name .depend -o -name .hdepend \) -type f -print | xargs rm -f - set -e; \ - cd $(TOPDIR)/.. ; \ - ln -sf $(TOPDIR) $(KERNELPATH) ; \ - tar -cvz --exclude CVS -f $(KERNELPATH).tar.gz $(KERNELPATH)/. ; \ - rm $(KERNELPATH) ; \ - cd $(TOPDIR) ; \ - . scripts/mkversion > .version ; \ - rpm -ta $(TOPDIR)/../$(KERNELPATH).tar.gz ; \ - rm $(TOPDIR)/../$(KERNELPATH).tar.gz - -# Scripts to check various things for consistency - -checkconfig: - find * -name '*.[hcS]' -type f -print | sort | xargs $(PERL) -w scripts/checkconfig.pl - -checkhelp: - find * -name [cC]onfig.in -print | sort | xargs $(PERL) -w scripts/checkhelp.pl - -checkincludes: - find * -name '*.[hcS]' -type f -print | sort | xargs $(PERL) -w scripts/checkincludes.pl - -# Generate tags for editors - -TAGS: FORCE - { find include/asm-${ARCH} -name '*.h' -print ; \ - find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print ; \ - find $(SUBDIRS) init -name '*.[ch]' ; } | grep -v SCCS | etags - - -# Exuberant ctags works better with -I -tags: FORCE - CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \ - ctags $$CTAGSF `find include/asm-$(ARCH) -name '*.h'` && \ - find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs ctags $$CTAGSF -a && \ - find $(SUBDIRS) init -name '*.[ch]' | xargs ctags $$CTAGSF -a - -# Make a backup -# FIXME anybody still using this? - -backup: mrproper - cd .. && tar cf - linux/ | gzip -9 > backup.gz - sync +# FIXME Should go into a make.lib or something +# =========================================================================== -# Make checksums -# FIXME anybody still using this? +# read all saved command lines -sums: - find . -type f -print | sort | xargs sum > .SUMS +cmd_files := $(wildcard .*.cmd) +ifneq ($(cmd_files),) + include $(cmd_files) +endif -# FIXME Should go into a make.lib or something -# --------------------------------------------------------------------------- +# Usage: $(call if_changed_rule,foo) +# will check if $(cmd_foo) changed, or any of the prequisites changed, +# and if so will execute $(rule_foo) if_changed_rule = $(if $(strip $? \ $(filter-out $(cmd_$(1)),$(cmd_$(@F)))\ diff -Nru a/README b/README --- a/README Sun Jun 2 18:44:57 2002 +++ b/README Sun Jun 2 18:44:57 2002 @@ -153,8 +153,9 @@ COMPILING the kernel: - - Make sure you have gcc 2.95.3 available. gcc 2.91.66 (egcs-1.1.2) may - also work but is not as safe, and *gcc 2.7.2.3 is no longer supported*. + - Make sure you have gcc 2.95.3 available. + gcc 2.91.66 (egcs-1.1.2), and gcc 2.7.2.3 are known to miscompile + some parts of the kernel, and are *no longer supported*. Also remember to upgrade your binutils package (for as/ld/nm and company) if necessary. For more information, refer to ./Documentation/Changes. diff -Nru a/Rules.make b/Rules.make --- a/Rules.make Sun Jun 2 18:44:57 2002 +++ b/Rules.make Sun Jun 2 18:44:57 2002 @@ -291,9 +291,6 @@ # ifdef CONFIG_MODULES -multi-objs := $(foreach m, $(obj-y) $(obj-m), $($(basename $(m))-objs)) -active-objs := $(sort $(multi-objs) $(obj-y) $(obj-m)) - ifdef CONFIG_MODVERSIONS ifneq "$(strip $(export-objs))" "" @@ -311,38 +308,37 @@ genksyms_smp_prefix := endif -$(MODINCL)/$(MODPREFIX)%.ver: %.c - @if [ ! -r $(MODINCL)/$(MODPREFIX)$*.stamp -o $(MODINCL)/$(MODPREFIX)$*.stamp -ot $< ]; then \ - echo '$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -D__GENKSYMS__ $<'; \ - echo '| $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp'; \ - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -D__GENKSYMS__ $< \ - | $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp; \ - if [ -r $@ ] && cmp -s $@ $@.tmp; then echo $@ is unchanged; rm -f $@.tmp; \ - else echo mv $@.tmp $@; mv -f $@.tmp $@; fi; \ - fi; touch $(MODINCL)/$(MODPREFIX)$*.stamp +# We don't track dependencies for .ver files, so we FORCE to check +# them always (i.e. always at "make dep" time). + +cmd_create_ver = $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -D__GENKSYMS__ $< | \ + $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp -$(addprefix $(MODINCL)/$(MODPREFIX),$(export-objs:.o=.ver)): $(TOPDIR)/include/linux/autoconf.h +$(MODINCL)/$(MODPREFIX)%.ver: %.c FORCE + @echo $(cmd_create_ver) + @$(cmd_create_ver) + @if [ -r $@ ] && cmp -s $@ $@.tmp; then \ + echo $@ is unchanged; rm -f $@.tmp; \ + else \ + echo mv $@.tmp $@; mv -f $@.tmp $@; \ + fi # updates .ver files but not modversions.h fastdep: $(addprefix $(MODINCL)/$(MODPREFIX),$(export-objs:.o=.ver)) endif # export-objs -$(active-objs): $(TOPDIR)/include/linux/modversions.h +# make dep cannot correctly figure out the dependency on the generated +# modversions.h, so we list them here: +# o files which export symbols and are compiled into the kernel include +# it (to generate a correct symbol table) +# o all modules get compiled with -include modversions.h -else - -$(TOPDIR)/include/linux/modversions.h: - @echo "#include " > $@ +$(filter $(export-objs),$(real-objs-y)): $(TOPDIR)/include/linux/modversions.h +$(real-objs-m): $(TOPDIR)/include/linux/modversions.h endif # CONFIG_MODVERSIONS -ifneq "$(strip $(export-objs))" "" - -$(export-objs): $(TOPDIR)/include/linux/modversions.h - -endif - endif # CONFIG_MODULES # @@ -400,4 +396,3 @@ $(filter-out $($(1)),$(cmd_$(@F)))\ $(filter-out $(cmd_$(@F)),$($(1)))),\ @echo '$($(1))' && $($(1)) && echo 'cmd_$@ := $($(1))' > $(@D)/.$(@F).cmd) - diff -Nru a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c --- a/arch/arm/boot/compressed/misc.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/boot/compressed/misc.c Sun Jun 2 18:44:56 2002 @@ -22,7 +22,6 @@ #include #include -#include #ifdef STANDALONE_DEBUG #define puts printf @@ -291,7 +290,6 @@ free_mem_ptr_end = free_mem_ptr_end_p; __machine_arch_type = arch_id; - proc_decomp_setup(); arch_decomp_setup(); makecrc(); diff -Nru a/arch/arm/config.in b/arch/arm/config.in --- a/arch/arm/config.in Sun Jun 2 18:44:56 2002 +++ b/arch/arm/config.in Sun Jun 2 18:44:56 2002 @@ -63,11 +63,6 @@ dep_bool ' Brutus' CONFIG_SA1100_BRUTUS $CONFIG_ARCH_SA1100 dep_bool ' CerfBoard' CONFIG_SA1100_CERF $CONFIG_ARCH_SA1100 if [ "$CONFIG_SA1100_CERF" = "y" ]; then - choice 'Cerf RAM available' \ - "8MB CONFIG_SA1100_CERF_8MB \ - 16MB CONFIG_SA1100_CERF_16MB \ - 32MB CONFIG_SA1100_CERF_32MB \ - 64MB CONFIG_SA1100_CERF_64MB" CerfRam choice 'Cerf Flash available' \ "8MB CONFIG_SA1100_CERF_FLASH_8MB \ 16MB CONFIG_SA1100_CERF_FLASH_16MB \ @@ -453,7 +448,9 @@ fi comment 'At least one math emulation must be selected' tristate 'NWFPE math emulation' CONFIG_FPE_NWFPE -dep_tristate 'FastFPE math emulation (experimental)' CONFIG_FPE_FASTFPE $CONFIG_EXPERIMENTAL +if [ "$CONFIG_CPU_26" = "n" -a "$CONFIG_CPU_32v3" = "n" ]; then + dep_tristate 'FastFPE math emulation (experimental)' CONFIG_FPE_FASTFPE $CONFIG_EXPERIMENTAL +fi choice 'Kernel core (/proc/kcore) format' \ "ELF CONFIG_KCORE_ELF \ A.OUT CONFIG_KCORE_AOUT" ELF @@ -494,15 +491,10 @@ fi fi -if [ "$CONFIG_ARCH_SA1100" = "y" ]; then +if [ "$CONFIG_CPU_32" = "y" ]; then define_bool CONFIG_ALIGNMENT_TRAP y else - if [ "$CONFIG_CPU_32" = "y" -a \ - "$CONFIG_ARCH_EBSA110" != "y" ]; then - bool 'Mis-alignment trap handler' CONFIG_ALIGNMENT_TRAP - else - define_bool CONFIG_ALIGNMENT_TRAP n - fi + define_bool CONFIG_ALIGNMENT_TRAP n fi endmenu @@ -510,6 +502,8 @@ if [ "$CONFIG_ALIGNMENT_TRAP" = "y" ]; then source drivers/mtd/Config.in +else + define_bool CONFIG_MTD n fi source drivers/pnp/Config.in diff -Nru a/arch/arm/def-configs/adi_evb b/arch/arm/def-configs/adi_evb --- a/arch/arm/def-configs/adi_evb Sun Jun 2 18:44:57 2002 +++ b/arch/arm/def-configs/adi_evb Sun Jun 2 18:44:57 2002 @@ -147,7 +147,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/mtdblock1" +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/mtdblock1 mem=32M initrd=0xc0800000,3M" CONFIG_ALIGNMENT_TRAP=y # @@ -236,7 +236,7 @@ # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4192 +CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_BLK_DEV_INITRD=y # diff -Nru a/arch/arm/def-configs/adsbitsy b/arch/arm/def-configs/adsbitsy --- a/arch/arm/def-configs/adsbitsy Sun Jun 2 18:44:58 2002 +++ b/arch/arm/def-configs/adsbitsy Sun Jun 2 18:44:58 2002 @@ -139,7 +139,7 @@ # CONFIG_PM is not set # CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="ip=off" +CONFIG_CMDLINE="ip=off mem=32M root=/dev/ram ramdisk=8192 initrd=0xc0800000,4M" # CONFIG_PFS168_CMDLINE is not set # CONFIG_LEDS is not set CONFIG_ALIGNMENT_TRAP=y diff -Nru a/arch/arm/def-configs/anakin b/arch/arm/def-configs/anakin --- a/arch/arm/def-configs/anakin Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/anakin Sun Jun 2 18:44:56 2002 @@ -8,12 +8,21 @@ CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_GENERIC_BUST_SPINLOCK is not set +# CONFIG_GENERIC_ISA_DMA is not set # # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set + +# +# General setup +# +CONFIG_NET=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set # # Loadable module support @@ -25,17 +34,21 @@ # # System Type # +# CONFIG_ARCH_ADIFCC is not set +CONFIG_ARCH_ANAKIN=y # CONFIG_ARCH_ARCA5K is not set # CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP310 is not set +# CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_CLPS711X is not set -CONFIG_ARCH_ANAKIN=y +# CONFIG_ARCH_SHARK is not set # # Archimedes/A5000 Implementations @@ -61,12 +74,19 @@ # # CONFIG_SA1100_ASSABET is not set # CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSBITSY is not set # CONFIG_SA1100_BRUTUS is not set # CONFIG_SA1100_CERF is not set -# CONFIG_SA1100_BITSY is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_H3XXX is not set # CONFIG_SA1100_EXTENEX1 is not set +# CONFIG_SA1100_FLEXANET is not set # CONFIG_SA1100_FREEBIRD is not set # CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_BADGE4 is not set # CONFIG_SA1100_JORNADA720 is not set # CONFIG_SA1100_HUW_WEBPANEL is not set # CONFIG_SA1100_ITSY is not set @@ -75,16 +95,31 @@ # CONFIG_SA1100_OMNIMETER is not set # CONFIG_SA1100_PANGOLIN is not set # CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set # CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_SIMPAD is not set # CONFIG_SA1100_PFS168 is not set # CONFIG_SA1100_VICTOR is not set # CONFIG_SA1100_XP860 is not set # CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_STORK is not set +# CONFIG_SA1100_USB is not set +# CONFIG_SA1100_USB_NETLINK is not set +# CONFIG_SA1100_USB_CHAR is not set +# CONFIG_H3600_SLEEVE is not set # # CLPS711X/EP721X Implementations # +# CONFIG_ARCH_AUTCPU12 is not set +# CONFIG_ARCH_CDB89712 is not set +# CONFIG_ARCH_CLEP7312 is not set +# CONFIG_ARCH_EDB7211 is not set # CONFIG_ARCH_P720T is not set +# CONFIG_ARCH_FORTUNET is not set +# CONFIG_ARCH_EP7211 is not set +# CONFIG_ARCH_EP7212 is not set # CONFIG_ARCH_ACORN is not set # CONFIG_FOOTBRIDGE is not set # CONFIG_FOOTBRIDGE_HOST is not set @@ -97,27 +132,40 @@ # # CONFIG_CPU_32v3 is not set CONFIG_CPU_32v4=y +# CONFIG_CPU_32v5 is not set # CONFIG_CPU_ARM610 is not set # CONFIG_CPU_ARM710 is not set # CONFIG_CPU_ARM720T is not set # CONFIG_CPU_ARM920T is not set +# CONFIG_CPU_ARM922T is not set +# CONFIG_CPU_ARM926T is not set # CONFIG_CPU_ARM1020 is not set CONFIG_CPU_SA110=y # CONFIG_CPU_SA1100 is not set -# CONFIG_DISCONTIGMEM is not set +# CONFIG_CPU_XSCALE is not set +# CONFIG_XSCALE_PMU is not set + +# +# Processor Features +# # # General setup # +# CONFIG_DISCONTIGMEM is not set # CONFIG_PCI is not set # CONFIG_ISA is not set # CONFIG_ISA_DMA is not set +# CONFIG_FIQ is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 # CONFIG_HOTPLUG is not set # CONFIG_PCMCIA is not set -CONFIG_NET=y -# CONFIG_SYSVIPC is not set -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_SYSCTL is not set + +# +# At least one math emulation must be selected +# CONFIG_FPE_NWFPE=y # CONFIG_FPE_FASTFPE is not set CONFIG_KCORE_ELF=y @@ -126,9 +174,11 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set +# CONFIG_PREEMPT is not set +# CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="" -# CONFIG_ALIGNMENT_TRAP is not set +CONFIG_CMDLINE="root=/dev/ram initrd=0xc0800000,4M" +CONFIG_ALIGNMENT_TRAP=y # # Parallel port support @@ -136,10 +186,16 @@ # CONFIG_PARPORT is not set # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Plug and Play configuration # # CONFIG_PNP is not set # CONFIG_ISAPNP is not set +# CONFIG_PNPBIOS is not set # # Block devices @@ -149,7 +205,9 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_CISS_SCSI_TAPE is not set # CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y @@ -165,13 +223,14 @@ # CONFIG_MD_RAID0 is not set # CONFIG_MD_RAID1 is not set # CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set # CONFIG_BLK_DEV_LVM is not set # # Networking options # # CONFIG_PACKET is not set -# CONFIG_NETLINK is not set +# CONFIG_NETLINK_DEV is not set # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y @@ -181,17 +240,24 @@ # CONFIG_IP_PNP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set # # # # CONFIG_IPX is not set # CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set @@ -229,7 +295,13 @@ # CONFIG_IRLAN is not set # CONFIG_IRCOMM is not set # CONFIG_IRDA_ULTRA is not set -# CONFIG_IRDA_OPTIONS is not set + +# +# IrDA options +# +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set # # Infrared-port device drivers @@ -242,24 +314,25 @@ # CONFIG_IRPORT_SIR is not set # +# Dongle support +# +# CONFIG_DONGLE is not set + +# # FIR device drivers # +# CONFIG_USB_IRDA is not set # CONFIG_NSC_FIR is not set # CONFIG_WINBOND_FIR is not set # CONFIG_TOSHIBA_FIR is not set # CONFIG_SMC_IRCC_FIR is not set -# CONFIG_SA1100_FIR is not set - -# -# Dongle support -# -# CONFIG_DONGLE is not set +# CONFIG_ALI_FIR is not set +# CONFIG_VLSI_FIR is not set # # ATA/IDE/MFM/RLL support # # CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set # CONFIG_BLK_DEV_HD is not set # @@ -279,27 +352,73 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set # -# Input core support +# Input device support # # CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_GAMEPORT_NS558 is not set +# CONFIG_GAMEPORT_L4 is not set +# CONFIG_INPUT_EMU10K1 is not set +# CONFIG_GAMEPORT_PCIGAME is not set +# CONFIG_GAMEPORT_FM801 is not set +# CONFIG_GAMEPORT_CS461x is not set +# CONFIG_SERIO is not set +# CONFIG_SERIO_SERPORT is not set # # Character devices # CONFIG_VT=y # CONFIG_VT_CONSOLE is not set -# CONFIG_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# + +# +# ARM Serial drivers +# +# CONFIG_ATOMWIDE_SERIAL is not set +# CONFIG_DUALSP_SERIAL is not set CONFIG_SERIAL_ANAKIN=y CONFIG_SERIAL_ANAKIN_CONSOLE=y CONFIG_ANAKIN_DEFAULT_BAUDRATE=115200 -CONFIG_TOUCHSCREEN_ANAKIN=y +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X is not set +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set +# CONFIG_SERIAL_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_UART00 is not set +# CONFIG_SERIAL_UART00_CONSOLE is not set +# CONFIG_SERIAL_SA1100 is not set +# CONFIG_SERIAL_SA1100_CONSOLE is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_TOUCHSCREEN_ANAKIN=y # CONFIG_UNIX98_PTYS is not set # @@ -308,19 +427,23 @@ # CONFIG_I2C is not set # -# Mice +# L3 serial bus support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set +# CONFIG_L3 is not set +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set # -# Joysticks +# Other L3 adapters # -# CONFIG_JOYSTICK is not set +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set # -# Input core support is needed for joysticks +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set # CONFIG_QIC02_TAPE is not set # @@ -350,27 +473,40 @@ # File systems # # CONFIG_QUOTA is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +# CONFIG_QIFACE_COMPAT is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set # CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set +CONFIG_RAMFS=y # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_JFS_FS is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set # CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_DEBUG is not set # CONFIG_HPFS_FS is not set @@ -384,7 +520,6 @@ # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set @@ -394,13 +529,16 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set # CONFIG_NFS_FS is not set # CONFIG_NFS_V3 is not set # CONFIG_ROOT_NFS is not set # CONFIG_NFSD is not set # CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set # CONFIG_SUNRPC is not set # CONFIG_LOCKD is not set +# CONFIG_EXPORTFS is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set # CONFIG_NCPFS_PACKET_SIGNING is not set @@ -411,12 +549,12 @@ # CONFIG_NCPFS_SMALLDOS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y # CONFIG_SMB_NLS is not set # CONFIG_NLS is not set @@ -425,7 +563,6 @@ # CONFIG_PC_KEYMAP=y # CONFIG_VGA_CONSOLE is not set -CONFIG_FB=y # # Frame-buffer support @@ -433,11 +570,10 @@ CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y # CONFIG_FB_ACORN is not set +CONFIG_FB_ANAKIN=y # CONFIG_FB_CLPS711X is not set -# CONFIG_FB_CYBER2000 is not set # CONFIG_FB_SA1100 is not set -CONFIG_FB_ANAKIN=y -# CONFIG_FB_E1355 is not set +# CONFIG_FB_CYBER2000 is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set CONFIG_FBCON_CFB16=y @@ -447,19 +583,49 @@ CONFIG_FONT_8x16=y # +# Multimedia Capabilities Port drivers +# +# CONFIG_MCP is not set +# CONFIG_MCP_SA1100 is not set +# CONFIG_MCP_UCB1200 is not set +# CONFIG_MCP_UCB1200_AUDIO is not set +# CONFIG_MCP_UCB1200_TS is not set + +# +# Console Switches +# +# CONFIG_SWITCHES is not set + +# # USB support # # CONFIG_USB is not set # +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# # Kernel hacking # # CONFIG_NO_FRAME_POINTER is not set -CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_USER=y # CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_MAGIC_SYSRQ is not set -# CONFIG_NO_PGT_CACHE is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_ERRORS is not set # CONFIG_DEBUG_LL is not set # CONFIG_DEBUG_DC21285_PORT is not set # CONFIG_DEBUG_CLPS711X_UART2 is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +# CONFIG_ZLIB_INFLATE is not set +# CONFIG_ZLIB_DEFLATE is not set diff -Nru a/arch/arm/def-configs/assabet b/arch/arm/def-configs/assabet --- a/arch/arm/def-configs/assabet Sun Jun 2 18:44:57 2002 +++ b/arch/arm/def-configs/assabet Sun Jun 2 18:44:57 2002 @@ -157,7 +157,7 @@ # CONFIG_BINFMT_MISC is not set CONFIG_PM=y # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="" +CONFIG_CMDLINE="mem=32M console=ttySA0,38400n8 initrd=0xc0800000,3M root=/dev/ram" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y @@ -833,6 +833,13 @@ CONFIG_MCP_UCB1200=y CONFIG_MCP_UCB1200_AUDIO=m CONFIG_MCP_UCB1200_TS=y + +# +# Console Switches +# +CONFIG_SWITCHES=y +CONFIG_SWITCHES_SA1100=y +CONFIG_SWITCHES_UCB1X00=y # # USB support diff -Nru a/arch/arm/def-configs/badge4 b/arch/arm/def-configs/badge4 --- a/arch/arm/def-configs/badge4 Sun Jun 2 18:44:58 2002 +++ b/arch/arm/def-configs/badge4 Sun Jun 2 18:44:58 2002 @@ -527,7 +527,6 @@ # CONFIG_BLK_DEV_IDETAPE is not set CONFIG_BLK_DEV_IDEFLOPPY=m CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set # # IDE chipset support/bugfixes diff -Nru a/arch/arm/def-configs/brutus b/arch/arm/def-configs/brutus --- a/arch/arm/def-configs/brutus Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/brutus Sun Jun 2 18:44:56 2002 @@ -76,7 +76,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" +CONFIG_CMDLINE="mem=4M@0xc0000000 mem=4M@0xc8000000 mem=4M@0xd0000000 mem=4M@0xd8000000 keepinitrd root=/dev/ram ramdisk=8192 initrd=0xd8000000,3M" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y diff -Nru a/arch/arm/def-configs/cerfcube b/arch/arm/def-configs/cerfcube --- a/arch/arm/def-configs/cerfcube Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/cerfcube Sun Jun 2 18:44:56 2002 @@ -65,10 +65,6 @@ # CONFIG_SA1100_ADSBITSY is not set # CONFIG_SA1100_BRUTUS is not set CONFIG_SA1100_CERF=y -# CONFIG_SA1100_CERF_8MB is not set -# CONFIG_SA1100_CERF_16MB is not set -CONFIG_SA1100_CERF_32MB=y -# CONFIG_SA1100_CERF_64MB is not set # CONFIG_SA1100_CERF_FLASH_8MB is not set CONFIG_SA1100_CERF_FLASH_16MB=y # CONFIG_SA1100_CERF_FLASH_32MB is not set @@ -163,7 +159,7 @@ # CONFIG_PM is not set # CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="console=ttySA0 root=1f03 rw" +CONFIG_CMDLINE="console=ttySA0 root=/dev/mtdblock3 rw mem=32M" # CONFIG_PFS168_CMDLINE is not set CONFIG_LEDS=y CONFIG_LEDS_TIMER=y diff -Nru a/arch/arm/def-configs/cerfpda b/arch/arm/def-configs/cerfpda --- a/arch/arm/def-configs/cerfpda Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/cerfpda Sun Jun 2 18:44:56 2002 @@ -65,10 +65,6 @@ # CONFIG_SA1100_ADSBITSY is not set # CONFIG_SA1100_BRUTUS is not set CONFIG_SA1100_CERF=y -# CONFIG_SA1100_CERF_8MB is not set -# CONFIG_SA1100_CERF_16MB is not set -# CONFIG_SA1100_CERF_32MB is not set -CONFIG_SA1100_CERF_64MB=y # CONFIG_SA1100_CERF_FLASH_8MB is not set # CONFIG_SA1100_CERF_FLASH_16MB is not set CONFIG_SA1100_CERF_FLASH_32MB=y @@ -163,7 +159,7 @@ # CONFIG_PM is not set # CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="console=ttySA0 cpufreq_max=221200 root=1f03 rw" +CONFIG_CMDLINE="console=ttySA0 cpufreq_max=221200 root=/dev/mtdblock3 rw mem=64M" # CONFIG_PFS168_CMDLINE is not set # CONFIG_LEDS is not set CONFIG_ALIGNMENT_TRAP=y diff -Nru a/arch/arm/def-configs/cerfpod b/arch/arm/def-configs/cerfpod --- a/arch/arm/def-configs/cerfpod Sun Jun 2 18:44:58 2002 +++ b/arch/arm/def-configs/cerfpod Sun Jun 2 18:44:58 2002 @@ -65,10 +65,6 @@ # CONFIG_SA1100_ADSBITSY is not set # CONFIG_SA1100_BRUTUS is not set CONFIG_SA1100_CERF=y -# CONFIG_SA1100_CERF_8MB is not set -# CONFIG_SA1100_CERF_16MB is not set -CONFIG_SA1100_CERF_32MB=y -# CONFIG_SA1100_CERF_64MB is not set # CONFIG_SA1100_CERF_FLASH_8MB is not set CONFIG_SA1100_CERF_FLASH_16MB=y # CONFIG_SA1100_CERF_FLASH_32MB is not set @@ -163,7 +159,7 @@ # CONFIG_PM is not set # CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="console=ttySA0 root=1f03 rw" +CONFIG_CMDLINE="console=ttySA0 root=/dev/mtdblock3 rw mem=32M" # CONFIG_PFS168_CMDLINE is not set CONFIG_LEDS=y CONFIG_LEDS_TIMER=y diff -Nru a/arch/arm/def-configs/empeg b/arch/arm/def-configs/empeg --- a/arch/arm/def-configs/empeg Sun Jun 2 18:44:57 2002 +++ b/arch/arm/def-configs/empeg Sun Jun 2 18:44:57 2002 @@ -56,7 +56,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_ARTHUR is not set # CONFIG_PARPORT is not set -CONFIG_CMDLINE="" +CONFIG_CMDLINE="mem=4M@0xc0000000 mem=4M@0xc8000000 root=/dev/hda1 initrd=0xd00b0000,320K" # # Plug and Play support diff -Nru a/arch/arm/def-configs/epxa10db b/arch/arm/def-configs/epxa10db --- a/arch/arm/def-configs/epxa10db Sun Jun 2 18:44:57 2002 +++ b/arch/arm/def-configs/epxa10db Sun Jun 2 18:44:57 2002 @@ -156,7 +156,7 @@ # CONFIG_PM is not set # CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="console=ttyUA0,38400 root=/dev/mtdblock0 rw" +CONFIG_CMDLINE="mem=32M console=ttyUA0,38400 root=/dev/mtdblock0 rw" CONFIG_ALIGNMENT_TRAP=y # diff -Nru a/arch/arm/def-configs/flexanet b/arch/arm/def-configs/flexanet --- a/arch/arm/def-configs/flexanet Sun Jun 2 18:44:57 2002 +++ b/arch/arm/def-configs/flexanet Sun Jun 2 18:44:57 2002 @@ -162,7 +162,7 @@ # CONFIG_BINFMT_MISC is not set CONFIG_PM=y # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="" +CONFIG_CMDLINE="mem=64M root=/dev/ram initrd=0xc0800000,3M" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y @@ -263,7 +263,7 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_BLK_DEV_INITRD=y # diff -Nru a/arch/arm/def-configs/freebird b/arch/arm/def-configs/freebird --- a/arch/arm/def-configs/freebird Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/freebird Sun Jun 2 18:44:56 2002 @@ -131,7 +131,7 @@ CONFIG_PM=y CONFIG_APM=y # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="mem=32M" +CONFIG_CMDLINE="mem=32M root=/dev/ram initrd=0xc0800000,3M" # CONFIG_PFS168_CMDLINE is not set # CONFIG_LEDS is not set CONFIG_ALIGNMENT_TRAP=y @@ -202,7 +202,7 @@ CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_BLK_DEV_INITRD=y # diff -Nru a/arch/arm/def-configs/freebird_new b/arch/arm/def-configs/freebird_new --- a/arch/arm/def-configs/freebird_new Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/freebird_new Sun Jun 2 18:44:56 2002 @@ -131,7 +131,7 @@ CONFIG_PM=y CONFIG_APM=y # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="noinitrd console=ttySA0 init=/linuxrc root=1f04 mem=32m" +CONFIG_CMDLINE="noinitrd console=ttySA0 init=/linuxrc root=/dev/mtdblock4 mem=32m" # CONFIG_PFS168_CMDLINE is not set # CONFIG_LEDS is not set CONFIG_ALIGNMENT_TRAP=y diff -Nru a/arch/arm/def-configs/graphicsclient b/arch/arm/def-configs/graphicsclient --- a/arch/arm/def-configs/graphicsclient Sun Jun 2 18:44:57 2002 +++ b/arch/arm/def-configs/graphicsclient Sun Jun 2 18:44:57 2002 @@ -146,7 +146,7 @@ # CONFIG_PM is not set # CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="ip=off" +CONFIG_CMDLINE="ip=off mem=16M@0xc0000000 mem=16M@0xc8000000 root=/dev/ram initrd=0xc0800000,4M" # CONFIG_PFS168_CMDLINE is not set CONFIG_LEDS=y CONFIG_LEDS_TIMER=y diff -Nru a/arch/arm/def-configs/graphicsmaster b/arch/arm/def-configs/graphicsmaster --- a/arch/arm/def-configs/graphicsmaster Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/graphicsmaster Sun Jun 2 18:44:56 2002 @@ -139,7 +139,7 @@ # CONFIG_PM is not set # CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="ip=off" +CONFIG_CMDLINE="ip=off mem=16M@0xc0000000 mem=16M@0xc8000000 root=/dev/ram initrd=0xc0800000,4M" # CONFIG_PFS168_CMDLINE is not set CONFIG_LEDS=y CONFIG_LEDS_TIMER=y diff -Nru a/arch/arm/def-configs/huw_webpanel b/arch/arm/def-configs/huw_webpanel --- a/arch/arm/def-configs/huw_webpanel Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/huw_webpanel Sun Jun 2 18:44:56 2002 @@ -96,7 +96,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" +CONFIG_CMDLINE="keepinitrd mem=32480K root=/dev/ram initrd=0xc0800000,8M" # CONFIG_LEDS is not set CONFIG_ALIGNMENT_TRAP=y @@ -167,7 +167,7 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_BLK_DEV_INITRD=y # CONFIG_BLK_DEV_FLASH is not set diff -Nru a/arch/arm/def-configs/iq80310 b/arch/arm/def-configs/iq80310 --- a/arch/arm/def-configs/iq80310 Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/iq80310 Sun Jun 2 18:44:56 2002 @@ -161,7 +161,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="console=ttyS0,115200 ip=bootp" +CONFIG_CMDLINE="console=ttyS0,115200 ip=bootp mem=32M root=/dev/nfs initrd=0xc0800000,4M" CONFIG_ALIGNMENT_TRAP=y # diff -Nru a/arch/arm/def-configs/jornada720 b/arch/arm/def-configs/jornada720 --- a/arch/arm/def-configs/jornada720 Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/jornada720 Sun Jun 2 18:44:56 2002 @@ -158,7 +158,7 @@ CONFIG_PM=y # CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" +CONFIG_CMDLINE="keepinitrd mem=32M" # CONFIG_LEDS is not set CONFIG_ALIGNMENT_TRAP=y diff -Nru a/arch/arm/def-configs/lusl7200 b/arch/arm/def-configs/lusl7200 --- a/arch/arm/def-configs/lusl7200 Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/lusl7200 Sun Jun 2 18:44:56 2002 @@ -2,7 +2,14 @@ # Automatically generated make config: don't edit # CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_GENERIC_BUST_SPINLOCK is not set +# CONFIG_GENERIC_ISA_DMA is not set # # Code maturity level options @@ -10,50 +17,169 @@ CONFIG_EXPERIMENTAL=y # -# System and Processor Type +# General setup # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set -# CONFIG_ARCH_RPC is not set +# CONFIG_NET is not set +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ADIFCC is not set +# CONFIG_ARCH_ANAKIN is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_FOOTBRIDGE is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP310 is not set CONFIG_ARCH_L7200=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set + +# +# Archimedes/A5000 Implementations +# + +# +# Archimedes/A5000 Implementations (select only ONE) +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set + +# +# Footbridge Implementations +# +# CONFIG_ARCH_CATS is not set +# CONFIG_ARCH_PERSONAL_SERVER is not set +# CONFIG_ARCH_EBSA285_ADDIN is not set +# CONFIG_ARCH_EBSA285_HOST is not set +# CONFIG_ARCH_NETWINDER is not set + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSBITSY is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_H3XXX is not set +# CONFIG_SA1100_EXTENEX1 is not set +# CONFIG_SA1100_FLEXANET is not set +# CONFIG_SA1100_FREEBIRD is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_BADGE4 is not set +# CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HUW_WEBPANEL is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_OMNIMETER is not set +# CONFIG_SA1100_PANGOLIN is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_PFS168 is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_STORK is not set +# CONFIG_SA1100_USB is not set +# CONFIG_SA1100_USB_NETLINK is not set +# CONFIG_SA1100_USB_CHAR is not set +# CONFIG_H3600_SLEEVE is not set + +# +# CLPS711X/EP721X Implementations +# +# CONFIG_ARCH_AUTCPU12 is not set +# CONFIG_ARCH_CDB89712 is not set +# CONFIG_ARCH_CLEP7312 is not set +# CONFIG_ARCH_EDB7211 is not set +# CONFIG_ARCH_P720T is not set +# CONFIG_ARCH_FORTUNET is not set +# CONFIG_ARCH_EP7211 is not set +# CONFIG_ARCH_EP7212 is not set # CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set CONFIG_CPU_32=y # CONFIG_CPU_26 is not set + +# +# Processor Type +# +# CONFIG_CPU_32v3 is not set CONFIG_CPU_32v4=y -CONFIG_CPU_ARM720=y -CONFIG_ZBOOT_ROM=y -CONFIG_ZBOOT_ROM_TEXT=0x00010000 -CONFIG_ZBOOT_ROM_BSS=0xf03e0000 -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set -# CONFIG_SBUS is not set -# CONFIG_PCMCIA is not set -# CONFIG_ALIGNMENT_TRAP is not set +# CONFIG_CPU_32v5 is not set +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +CONFIG_CPU_ARM720T=y +# CONFIG_CPU_ARM920T is not set +# CONFIG_CPU_ARM922T is not set +# CONFIG_CPU_ARM926T is not set +# CONFIG_CPU_ARM1020 is not set +# CONFIG_CPU_SA110 is not set +# CONFIG_CPU_SA1100 is not set +# CONFIG_CPU_XSCALE is not set +# CONFIG_XSCALE_PMU is not set # -# Loadable module support +# Processor Features # -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y +# CONFIG_ARM_THUMB is not set # # General setup # -# CONFIG_NET is not set -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_NWFPE=y +# CONFIG_DISCONTIGMEM is not set +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +CONFIG_FIQ=y +CONFIG_ZBOOT_ROM=y +CONFIG_ZBOOT_ROM_TEXT=00010000 +CONFIG_ZBOOT_ROM_BSS=f03e0000 +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set + +# +# At least one math emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_PREEMPT is not set +# CONFIG_APM is not set # CONFIG_ARTHUR is not set +CONFIG_CMDLINE="console=tty0 console=ttyLU1,115200 root=/dev/ram initrd=0xf1000000,0x005dac7b mem=32M" +CONFIG_ALIGNMENT_TRAP=y # # Parallel port support @@ -61,18 +187,16 @@ # CONFIG_PARPORT is not set # -# I2O device support +# Memory Technology Devices (MTD) # -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set +# CONFIG_MTD is not set # # Plug and Play configuration # # CONFIG_PNP is not set # CONFIG_ISAPNP is not set +# CONFIG_PNPBIOS is not set # # Block devices @@ -81,28 +205,79 @@ # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_CISS_SCSI_TAPE is not set # CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_STRIPED is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y # +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# + +# +# Input device support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_GAMEPORT_NS558 is not set +# CONFIG_GAMEPORT_L4 is not set +# CONFIG_INPUT_EMU10K1 is not set +# CONFIG_GAMEPORT_PCIGAME is not set +# CONFIG_GAMEPORT_FM801 is not set +# CONFIG_GAMEPORT_CS461x is not set +# CONFIG_SERIO is not set +# CONFIG_SERIO_SERPORT is not set + +# # Character devices # # CONFIG_VT is not set -# CONFIG_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set CONFIG_SERIAL_NONSTANDARD=y # CONFIG_COMPUTONE is not set # CONFIG_ROCKETPORT is not set # CONFIG_CYCLADES is not set -CONFIG_SERIAL_L7200=y -CONFIG_SERIAL_L7200_CONSOLE=y # CONFIG_DIGIEPCA is not set # CONFIG_DIGI is not set # CONFIG_ESPSERIAL is not set @@ -110,11 +285,48 @@ # CONFIG_MOXA_SMARTIO is not set # CONFIG_ISI is not set # CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set # CONFIG_N_HDLC is not set # CONFIG_RISCOM8 is not set # CONFIG_SPECIALIX is not set # CONFIG_SX is not set +# CONFIG_RIO is not set # CONFIG_STALDRV is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# + +# +# ARM Serial drivers +# +# CONFIG_ATOMWIDE_SERIAL is not set +# CONFIG_DUALSP_SERIAL is not set +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X is not set +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set +# CONFIG_SERIAL_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_UART00 is not set +# CONFIG_SERIAL_UART00_CONSOLE is not set +# CONFIG_SERIAL_SA1100 is not set +# CONFIG_SERIAL_SA1100_CONSOLE is not set # CONFIG_UNIX98_PTYS is not set # @@ -123,28 +335,32 @@ # CONFIG_I2C is not set # -# Mice +# L3 serial bus support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set +# CONFIG_L3 is not set +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set # -# Joysticks +# Other L3 adapters # -# CONFIG_JOYSTICK is not set +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set # CONFIG_QIC02_TAPE is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -153,48 +369,58 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set -# CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set # CONFIG_AGP is not set +# CONFIG_DRM is not set # -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI support +# Multimedia devices # -# CONFIG_SCSI is not set +# CONFIG_VIDEO_DEV is not set # # File systems # # CONFIG_QUOTA is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +# CONFIG_QIFACE_COMPAT is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_RAMFS is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_JFS_FS is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set # CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_DEBUG is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set @@ -202,21 +428,36 @@ # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set # CONFIG_UFS_FS_WRITE is not set # CONFIG_NCPFS_NLS is not set +# CONFIG_SMB_FS is not set +# CONFIG_ZISOFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set # CONFIG_NLS is not set # +# Multimedia Capabilities Port drivers +# +# CONFIG_MCP is not set +# CONFIG_MCP_SA1100 is not set +# CONFIG_MCP_UCB1200 is not set +# CONFIG_MCP_UCB1200_AUDIO is not set +# CONFIG_MCP_UCB1200_TS is not set + +# +# Console Switches +# +# CONFIG_SWITCHES is not set + +# # USB support # # CONFIG_USB is not set @@ -224,9 +465,23 @@ # # Kernel hacking # -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_ERRORS=y +# CONFIG_NO_FRAME_POINTER is not set CONFIG_DEBUG_USER=y CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_MAGIC_SYSRQ is not set -CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +# CONFIG_ZLIB_INFLATE is not set +# CONFIG_ZLIB_DEFLATE is not set diff -Nru a/arch/arm/def-configs/neponset b/arch/arm/def-configs/neponset --- a/arch/arm/def-configs/neponset Sun Jun 2 18:44:57 2002 +++ b/arch/arm/def-configs/neponset Sun Jun 2 18:44:57 2002 @@ -821,6 +821,13 @@ CONFIG_MCP_UCB1200_TS=y # +# Console Switches +# +CONFIG_SWITCHES=y +CONFIG_SWITCHES_SA1100=y +CONFIG_SWITCHES_UCB1X00=y + +# # USB support # CONFIG_USB=y diff -Nru a/arch/arm/def-configs/omnimeter b/arch/arm/def-configs/omnimeter --- a/arch/arm/def-configs/omnimeter Sun Jun 2 18:44:57 2002 +++ b/arch/arm/def-configs/omnimeter Sun Jun 2 18:44:57 2002 @@ -100,7 +100,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" +CONFIG_CMDLINE="keepinitrd mem=16M root=/dev/ram ramdisk=8192 initrd=0xd0000000,4M" # CONFIG_LEDS is not set # CONFIG_ALIGNMENT_TRAP is not set diff -Nru a/arch/arm/def-configs/pangolin b/arch/arm/def-configs/pangolin --- a/arch/arm/def-configs/pangolin Sun Jun 2 18:44:57 2002 +++ b/arch/arm/def-configs/pangolin Sun Jun 2 18:44:57 2002 @@ -137,7 +137,7 @@ # CONFIG_PM is not set # CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" +CONFIG_CMDLINE="keepinitrd mem=128M root=/dev/ram initrd=0xc0800000,3M" # CONFIG_PFS168_CMDLINE is not set # CONFIG_LEDS is not set CONFIG_ALIGNMENT_TRAP=y @@ -249,7 +249,7 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_BLK_DEV_INITRD=y # diff -Nru a/arch/arm/def-configs/pfs168_mqtft b/arch/arm/def-configs/pfs168_mqtft --- a/arch/arm/def-configs/pfs168_mqtft Sun Jun 2 18:44:57 2002 +++ b/arch/arm/def-configs/pfs168_mqtft Sun Jun 2 18:44:57 2002 @@ -140,8 +140,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="root=/dev/nfs" -# CONFIG_PFS168_CMDLINE is not set +CONFIG_CMDLINE="root=/dev/nfs mem=16M" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y diff -Nru a/arch/arm/def-configs/pfs168_mqvga b/arch/arm/def-configs/pfs168_mqvga --- a/arch/arm/def-configs/pfs168_mqvga Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/pfs168_mqvga Sun Jun 2 18:44:56 2002 @@ -140,8 +140,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="root=/dev/nfs" -# CONFIG_PFS168_CMDLINE is not set +CONFIG_CMDLINE="root=/dev/nfs mem=16M" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y diff -Nru a/arch/arm/def-configs/pfs168_sastn b/arch/arm/def-configs/pfs168_sastn --- a/arch/arm/def-configs/pfs168_sastn Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/pfs168_sastn Sun Jun 2 18:44:56 2002 @@ -140,8 +140,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="root=/dev/nfs" -# CONFIG_PFS168_CMDLINE is not set +CONFIG_CMDLINE="root=/dev/nfs mem=16M" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y diff -Nru a/arch/arm/def-configs/pfs168_satft b/arch/arm/def-configs/pfs168_satft --- a/arch/arm/def-configs/pfs168_satft Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/pfs168_satft Sun Jun 2 18:44:56 2002 @@ -140,8 +140,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="root=/dev/nfs" -# CONFIG_PFS168_CMDLINE is not set +CONFIG_CMDLINE="root=/dev/nfs mem=16M" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y diff -Nru a/arch/arm/def-configs/pleb b/arch/arm/def-configs/pleb --- a/arch/arm/def-configs/pleb Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/pleb Sun Jun 2 18:44:56 2002 @@ -126,7 +126,7 @@ # CONFIG_PM is not set # CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="console=ttySA0,9600" +CONFIG_CMDLINE="console=ttySA0,9600 mem=16M@0xc0000000 mem=16M@0xc8000000 root=/dev/ram initrd=0xc0400000,4M" # CONFIG_PFS168_CMDLINE is not set # CONFIG_LEDS is not set CONFIG_ALIGNMENT_TRAP=y @@ -213,7 +213,7 @@ # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_BLK_DEV_INITRD=y # diff -Nru a/arch/arm/def-configs/sherman b/arch/arm/def-configs/sherman --- a/arch/arm/def-configs/sherman Sun Jun 2 18:44:56 2002 +++ b/arch/arm/def-configs/sherman Sun Jun 2 18:44:56 2002 @@ -60,7 +60,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_ARTHUR is not set # CONFIG_PARPORT is not set -CONFIG_CMDLINE="" +CONFIG_CMDLINE="mem=64M@0xc0000000 mem=64M@0xc8000000 root=/dev/mtdblock2" # # Plug and Play support diff -Nru a/arch/arm/def-configs/victor b/arch/arm/def-configs/victor --- a/arch/arm/def-configs/victor Sun Jun 2 18:44:56 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,206 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y - -# -# System and processor type -# -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_FOOTBRIDGE is not set -CONFIG_ARCH_SA1100=y -CONFIG_CPU_SA1100=y -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_EMPEG is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_PLEB is not set -CONFIG_SA1100_VICTOR=y -# CONFIG_VICTOR_BOARD1 is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_ISA_DMA is not set -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -# CONFIG_CPU_ARM2 is not set -# CONFIG_CPU_ARM3 is not set -# CONFIG_CPU_ARM6 is not set -# CONFIG_CPU_ARM7 is not set -CONFIG_CPU_SA110=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_ALIGNMENT_TRAP is not set -# CONFIG_TEXT_SECTIONS is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set - -# -# General setup -# -CONFIG_ZBOOT_ROM=y -CONFIG_ZBOOT_ROM_TEXT=0x00002000 -CONFIG_ZBOOT_ROM_BSS=0xc0200000 -# CONFIG_NET is not set -# CONFIG_SYSVIPC is not set -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_SYSCTL is not set -CONFIG_NWFPE=y -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -# CONFIG_ARTHUR is not set -# CONFIG_PARPORT is not set -CONFIG_CMDLINE="" - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_IDEDISK is not set -CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE_PARPORT=y -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_HD is not set - -# -# Character devices -# -# CONFIG_VT is not set -CONFIG_SERIAL_SA1100=y -CONFIG_SERIAL_SA1100_CONSOLE=y -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set -# CONFIG_MOUSE is not set -# CONFIG_QIC02_TAPE is not set -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set - -# -# Joystick support -# -# CONFIG_JOYSTICK is not set -# CONFIG_DTLK is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set - -# -# SCSI support -# -# CONFIG_SCSI is not set - -# -# Filesystems -# -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -# CONFIG_MINIX_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_PROC_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Partition Types -# -# CONFIG_OSF_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -# CONFIG_MSDOS_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ACORN_PARTITION is not set -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_CODEPAGE_437=y -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -CONFIG_NLS_CODEPAGE_850=y -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -CONFIG_NLS_ISO8859_1=y -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set - -# -# Kernel hacking -# -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_DEBUG_LL is not set diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S --- a/arch/arm/kernel/entry-armv.S Sun Jun 2 18:44:57 2002 +++ b/arch/arm/kernel/entry-armv.S Sun Jun 2 18:44:57 2002 @@ -958,20 +958,15 @@ .text /* * Register switch for ARMv3 and ARMv4 processors - * r0 = previous thread_info, r1 = next thread_info, return previous. + * r0 = previous thread_info, r1 = next thread_info * previous and next are guaranteed not to be the same. */ ENTRY(__switch_to) - stmfd sp!, {r4 - sl, fp, lr} @ Store most regs on stack - mrs ip, cpsr - str ip, [sp, #-4]! @ Save cpsr_SVC - str sp, [r0, #TI_CPU_SAVE] @ Save sp_SVC - ldr sp, [r1, #TI_CPU_SAVE] @ Get saved sp_SVC - ldr r2, [r1, #TI_CPU_DOMAIN] - ldr ip, [sp], #4 + add ip, r0, #TI_CPU_SAVE + ldr r2, [r1, #TI_CPU_DOMAIN]! + stmia ip, {r4 - sl, fp, sp, lr} @ Store most regs on stack mcr p15, 0, r2, c3, c0 @ Set domain register - msr spsr, ip @ Save tasks CPSR into SPSR for this return - ldmfd sp!, {r4 - sl, fp, pc}^ @ Load all regs saved previously + ldmib r1, {r4 - sl, fp, sp, pc} @ Load all regs saved previously .section ".text.init",#alloc,#execinstr /* diff -Nru a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c --- a/arch/arm/kernel/process.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/kernel/process.c Sun Jun 2 18:44:57 2002 @@ -185,7 +185,7 @@ get_fs() == get_ds() ? "kernel" : "user"); #if defined(CONFIG_CPU_32) { - int ctrl, transbase, dac; + unsigned int ctrl, transbase, dac; __asm__ ( " mrc p15, 0, %0, c1, c0\n" " mrc p15, 0, %1, c2, c0\n" @@ -310,23 +310,21 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); -int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, - unsigned long unused, - struct task_struct * p, struct pt_regs * regs) +int +copy_thread(int nr, unsigned long clone_flags, unsigned long esp, + unsigned long unused, struct task_struct *p, struct pt_regs *regs) { + struct thread_info *thread = p->thread_info; struct pt_regs *childregs; - struct cpu_context_save *save; - childregs = ((struct pt_regs *)((unsigned long)p->thread_info + THREAD_SIZE)) - 1; + childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_SIZE - 8)) - 1; *childregs = *regs; childregs->ARM_r0 = 0; childregs->ARM_sp = esp; - save = ((struct cpu_context_save *)(childregs)) - 1; - *save = INIT_CSS; - save->pc |= (unsigned long)ret_from_fork; - - p->thread_info->cpu_context = save; + memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); + thread->cpu_context.sp = (unsigned long)childregs; + thread->cpu_context.pc = (unsigned long)ret_from_fork; return 0; } diff -Nru a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c --- a/arch/arm/kernel/setup.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/kernel/setup.c Sun Jun 2 18:44:56 2002 @@ -341,7 +341,7 @@ *cmdline_p = command_line; } -void __init +static void __init setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz) { #ifdef CONFIG_BLK_DEV_RAM @@ -359,7 +359,7 @@ /* * initial ram disk */ -void __init setup_initrd(unsigned int start, unsigned int size) +static void __init setup_initrd(unsigned int start, unsigned int size) { #ifdef CONFIG_BLK_DEV_INITRD if (start == 0) diff -Nru a/arch/arm/mach-adifcc/arch.c b/arch/arm/mach-adifcc/arch.c --- a/arch/arm/mach-adifcc/arch.c Sun Jun 2 18:44:58 2002 +++ b/arch/arm/mach-adifcc/arch.c Sun Jun 2 18:44:58 2002 @@ -21,27 +21,10 @@ extern void adifcc_map_io(void); extern void adifcc_init_irq(void); -static void __init -fixup_adifcc(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ -#ifdef CONFIG_ARCH_ADI_EVB - mi->bank[0].start = PHYS_OFFSET; - mi->bank[0].size = (32*1024*1024); - mi->bank[0].node = 0; - mi->nr_banks = 1; - - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( 0xc0800000, 3*1024*1024 ); - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); -#endif -} - #ifdef CONFIG_ARCH_ADI_EVB MACHINE_START(ADI_EVB, "ADI 80200FCC Evaluation Board") MAINTAINER("MontaVista Software Inc.") BOOT_MEM(0xc0000000, 0x00400000, 0xff400000) - FIXUP(fixup_adifcc) MAPIO(adifcc_map_io) INITIRQ(adifcc_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-anakin/arch.c b/arch/arm/mach-anakin/arch.c --- a/arch/arm/mach-anakin/arch.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/mach-anakin/arch.c Sun Jun 2 18:44:56 2002 @@ -19,28 +19,13 @@ #include #include -#ifndef CONFIG_BLK_DEV_RAM_SIZE -#define CONFIG_BLK_DEV_RAM_SIZE 4096 -#endif - extern void anakin_map_io(void); extern void genarch_init_irq(void); -static void __init -fixup_anakin(struct machine_desc *desc, struct tag *tag, - char **cmdline, struct meminfo *mi) -{ - ROOT_DEV = mk_kdev(RAMDISK_MAJOR, 0); - setup_ramdisk(1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE); - setup_initrd(0xc0800000, 4 * 1024 * 1024); -} - - MACHINE_START(ANAKIN, "Anakin") MAINTAINER("Wookey/Tak-Shing Chan") BOOT_MEM(0x20000000, 0x40000000, 0xe0000000) VIDEO(0x80000000, 0x8002db40) - FIXUP(fixup_anakin) MAPIO(anakin_map_io) INITIRQ(genarch_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c --- a/arch/arm/mach-clps711x/cdb89712.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/mach-clps711x/cdb89712.c Sun Jun 2 18:44:56 2002 @@ -44,12 +44,6 @@ LAST_DESC }; -static void __init -fixup_cdb89712(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ -} - static void __init cdb89712_map_io(void) { clps711x_map_io(); @@ -60,7 +54,6 @@ MAINTAINER("Ray Lehtiniemi") BOOT_MEM(0xc0000000, 0x80000000, 0xff000000) BOOT_PARAMS(0xc0000100) - FIXUP(fixup_cdb89712) MAPIO(cdb89712_map_io) INITIRQ(clps711x_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-epxa10db/arch.c b/arch/arm/mach-epxa10db/arch.c --- a/arch/arm/mach-epxa10db/arch.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-epxa10db/arch.c Sun Jun 2 18:44:57 2002 @@ -33,29 +33,9 @@ extern void epxa10db_map_io(void); extern void epxa10db_init_irq(void); - -static void __init -epxa10db_fixup(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - - mi->nr_banks = 1; - mi->bank[0].start = 0; - mi->bank[0].size = (32*1024*1024); - mi->bank[0].node = 0; - -/* - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd(0xc0200000, 6*1024*1024); -*/ -} - MACHINE_START(CAMELOT, "Altera Epxa10db") MAINTAINER("Altera Corporation") BOOT_MEM(0x00000000, 0x7fffc000, 0xffffc000) - FIXUP(epxa10db_fixup) MAPIO(epxa10db_map_io) INITIRQ(epxa10db_init_irq) - MACHINE_END diff -Nru a/arch/arm/mach-integrator/arch.c b/arch/arm/mach-integrator/arch.c --- a/arch/arm/mach-integrator/arch.c Sun Jun 2 18:44:58 2002 +++ b/arch/arm/mach-integrator/arch.c Sun Jun 2 18:44:58 2002 @@ -50,9 +50,7 @@ }; #endif -static void __init -integrator_fixup(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) +static int __init integrator_init(void) { #ifdef CONFIG_KMI_KEYB register_kmi(&integrator_keyboard); @@ -60,11 +58,12 @@ #endif } +__initcall(integrator_init); + MACHINE_START(INTEGRATOR, "ARM-Integrator") MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd") BOOT_MEM(0x00000000, 0x16000000, 0xf1600000) BOOT_PARAMS(0x00000100) - FIXUP(integrator_fixup) MAPIO(integrator_map_io) INITIRQ(integrator_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c --- a/arch/arm/mach-integrator/cpu.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-integrator/cpu.c Sun Jun 2 18:44:57 2002 @@ -3,7 +3,7 @@ * * Copyright (C) 2001 Deep Blue Solutions Ltd. * - * $Id: cpu.c,v 1.2 2001/09/22 12:11:17 rmk Exp $ + * $Id: cpu.c,v 1.4 2002/05/29 11:41:55 rmk Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -121,7 +121,7 @@ cpu_freq_khz = vco_to_freq(vco, 1); #ifdef CONFIG_CPU_FREQ - cpufreq_init(cpu_freq_khz); + cpufreq_init(cpu_freq_khz, 1000, 0); cpufreq_setfunctions(integrator_validatespeed, integrator_setspeed); #endif diff -Nru a/arch/arm/mach-iop310/arch.c b/arch/arm/mach-iop310/arch.c --- a/arch/arm/mach-iop310/arch.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-iop310/arch.c Sun Jun 2 18:44:58 2002 @@ -31,21 +31,8 @@ { system_rev = (*(volatile unsigned int*)0xfe830000) & 0x0f; - if(system_rev) + if (system_rev) system_rev = 0xF; - - mi->bank[0].start = PHYS_OFFSET; - mi->bank[0].size = (32*1024*1024); - mi->bank[0].node = 0; - mi->nr_banks = 1; - -#ifdef CONFIG_ROOT_NFS - ROOT_DEV = to_kdev_t(0x00FF); /* /dev/nfs pseudo device */ -#elif defined(CONFIG_BLK_DEV_INITRD) - setup_ramdisk( 1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE ); - setup_initrd( 0xc0800000, 4*1024*1024 ); - ROOT_DEV = mk_kdev(RAMDISK_MAJOR, 0); /* /dev/ram */ -#endif } MACHINE_START(IQ80310, "Cyclone IQ80310") diff -Nru a/arch/arm/mach-l7200/core.c b/arch/arm/mach-l7200/core.c --- a/arch/arm/mach-l7200/core.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/mach-l7200/core.c Sun Jun 2 18:44:56 2002 @@ -82,33 +82,9 @@ iotable_init(l7200_io_desc); } -static void __init -fixup_l7200(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - mi->nr_banks = 1; - mi->bank[0].start = PHYS_OFFSET; - mi->bank[0].size = (32*1024*1024); - mi->bank[0].node = 0; - - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE); - setup_initrd( __phys_to_virt(0xf1000000), 0x005dac7b); - - /* Serial Console COM2 and LCD */ - strcpy( *cmdline, "console=tty0 console=ttyLU1,115200"); - - /* Serial Console COM1 and LCD */ - //strcpy( *cmdline, "console=tty0 console=ttyLU0,115200"); - - /* Console on LCD */ - //strcpy( *cmdline, "console=tty0"); -} - MACHINE_START(L7200, "LinkUp Systems L7200") MAINTAINER("Steve Hill / Scott McConnell") BOOT_MEM(0xf0000000, 0x80040000, 0xd0000000) - FIXUP(fixup_l7200) MAPIO(l7200_map_io) INITIRQ(l7200_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c --- a/arch/arm/mach-pxa/idp.c Sun Jun 2 18:44:55 2002 +++ b/arch/arm/mach-pxa/idp.c Sun Jun 2 18:44:55 2002 @@ -68,23 +68,6 @@ pxa_init_irq(); } -static void __init -fixup_idp(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ -#ifdef PXA_IDP_REV02 - SET_BANK (0, 0xa0000000, 64*1024*1024); -#else - SET_BANK (0, 0xa0000000, 32*1024*1024); -#endif - mi->nr_banks = 1; -#if 0 - setup_ramdisk (1, 0, 0, 8192); - setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024); - ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); -#endif -} - static struct map_desc idp_io_desc[] __initdata = { /* virtual physical length domain r w c b */ @@ -132,7 +115,6 @@ MACHINE_START(PXA_IDP, "Accelent Xscale IDP") MAINTAINER("Accelent Systems Inc.") BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000) - FIXUP(fixup_idp) MAPIO(idp_map_io) INITIRQ(idp_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c --- a/arch/arm/mach-pxa/lubbock.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-pxa/lubbock.c Sun Jun 2 18:44:57 2002 @@ -119,19 +119,6 @@ __initcall(lubbock_init); -static void __init -fixup_lubbock(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK (0, 0xa0000000, 64*1024*1024); - mi->nr_banks = 1; -#if 0 - setup_ramdisk (1, 0, 0, 8192); - setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024); - ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); -#endif -} - static struct map_desc lubbock_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */ @@ -160,7 +147,6 @@ MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform") MAINTAINER("MontaVista Software Inc.") BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000) - FIXUP(fixup_lubbock) MAPIO(lubbock_map_io) INITIRQ(lubbock_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c --- a/arch/arm/mach-rpc/riscpc.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/mach-rpc/riscpc.c Sun Jun 2 18:44:56 2002 @@ -60,16 +60,6 @@ #endif -static void __init -fixup_riscpc(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - /* - * RiscPC can't handle half-word loads and stores - */ - elf_hwcap &= ~HWCAP_HALF; -} - static struct map_desc rpc_io_desc[] __initdata = { { SCREEN_BASE, SCREEN_START, 2*1048576, DOMAIN_IO, 0, 1, 0, 0 }, /* VRAM */ { IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1, 0, 0 }, /* IO space */ @@ -80,6 +70,11 @@ void __init rpc_map_io(void) { iotable_init(rpc_io_desc); + + /* + * RiscPC can't handle half-word loads and stores + */ + elf_hwcap &= ~HWCAP_HALF; } MACHINE_START(RISCPC, "Acorn-RiscPC") @@ -88,7 +83,6 @@ BOOT_PARAMS(0x10000100) DISABLE_PARPORT(0) DISABLE_PARPORT(1) - FIXUP(fixup_riscpc) MAPIO(rpc_map_io) INITIRQ(rpc_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile --- a/arch/arm/mach-sa1100/Makefile Sun Jun 2 18:44:58 2002 +++ b/arch/arm/mach-sa1100/Makefile Sun Jun 2 18:44:58 2002 @@ -99,8 +99,6 @@ obj-$(CONFIG_SA1100_STORK) += stork.o export-objs += stork.o -obj-$(CONFIG_SA1100_VICTOR) += victor.o - obj-$(CONFIG_SA1100_XP860) += xp860.o obj-$(CONFIG_SA1100_YOPY) += yopy.o diff -Nru a/arch/arm/mach-sa1100/adsbitsy.c b/arch/arm/mach-sa1100/adsbitsy.c --- a/arch/arm/mach-sa1100/adsbitsy.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/mach-sa1100/adsbitsy.c Sun Jun 2 18:44:56 2002 @@ -76,23 +76,6 @@ sa1100_init_irq(); } - -/* - * Initialization fixup - */ - -static void __init -fixup_adsbitsy(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 32*1024*1024 ); - mi->nr_banks = 1; - - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); -} - static struct map_desc adsbitsy_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */ @@ -135,7 +118,6 @@ MACHINE_START(ADSBITSY, "ADS Bitsy") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_adsbitsy) MAPIO(adsbitsy_map_io) INITIRQ(adsbitsy_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c --- a/arch/arm/mach-sa1100/assabet.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/mach-sa1100/assabet.c Sun Jun 2 18:44:56 2002 @@ -162,60 +162,12 @@ fixup_assabet(struct machine_desc *desc, struct tag *tags, char **cmdline, struct meminfo *mi) { - struct tag *t = tags; - /* This must be done before any call to machine_has_neponset() */ map_sa1100_gpio_regs(); get_assabet_scr(); if (machine_has_neponset()) printk("Neponset expansion board detected\n"); - - if (t->hdr.tag != ATAG_CORE) { - t->hdr.tag = ATAG_CORE; - t->hdr.size = tag_size(tag_core); - t->u.core.flags = 0; - t->u.core.pagesize = PAGE_SIZE; - t->u.core.rootdev = RAMDISK_MAJOR << 8 | 0; - t = tag_next(t); - - t->hdr.tag = ATAG_MEM; - t->hdr.size = tag_size(tag_mem32); - t->u.mem.start = 0xc0000000; - t->u.mem.size = 32 * 1024 * 1024; - t = tag_next(t); - - - /* - * Note that Neponset RAM is slower... - * and still untested. - * This would be a candidate for - * _real_ NUMA support. - */ - if (machine_has_neponset() && 0) { - t->hdr.tag = ATAG_MEM; - t->hdr.size = tag_size(tag_mem32); - t->u.mem.start = 0xd0000000; - t->u.mem.size = 32 * 1024 * 1024; - t = tag_next(t); - } - - t->hdr.tag = ATAG_RAMDISK; - t->hdr.size = tag_size(tag_ramdisk); - t->u.ramdisk.flags = 1; - t->u.ramdisk.size = 8192; - t->u.ramdisk.start = 0; - t = tag_next(t); - - t->hdr.tag = ATAG_INITRD; - t->hdr.size = tag_size(tag_initrd); - t->u.initrd.start = 0xc0800000; - t->u.initrd.size = 3 * 1024 * 1024; - t = tag_next(t); - - t->hdr.tag = ATAG_NONE; - t->hdr.size = 0; - } } diff -Nru a/arch/arm/mach-sa1100/brutus.c b/arch/arm/mach-sa1100/brutus.c --- a/arch/arm/mach-sa1100/brutus.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-sa1100/brutus.c Sun Jun 2 18:44:57 2002 @@ -21,22 +21,6 @@ #include "generic.h" - -static void __init -fixup_brutus(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 4*1024*1024 ); - SET_BANK( 1, 0xc8000000, 4*1024*1024 ); - SET_BANK( 2, 0xd0000000, 4*1024*1024 ); - SET_BANK( 3, 0xd8000000, 4*1024*1024 ); - mi->nr_banks = 4; - - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xd8000000), 3*1024*1024 ); -} - static void __init brutus_map_io(void) { sa1100_map_io(); @@ -51,7 +35,6 @@ MACHINE_START(BRUTUS, "Intel Brutus (SA1100 eval board)") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_brutus) MAPIO(brutus_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c --- a/arch/arm/mach-sa1100/cerf.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-sa1100/cerf.c Sun Jun 2 18:44:57 2002 @@ -35,33 +35,6 @@ set_irq_type(IRQ_GPIO_UCB1200_IRQ, IRQT_RISING); } -static void __init -fixup_cerf(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ -#if defined(CONFIG_SA1100_CERF_64MB) - SET_BANK( 0, 0xc0000000, 64*1024*1024 ); - mi->nr_banks = 1; -#elif defined(CONFIG_SA1100_CERF_32MB) - SET_BANK( 0, 0xc0000000, 32*1024*1024 ); - mi->nr_banks = 1; -#elif defined(CONFIG_SA1100_CERF_16MB) - SET_BANK( 0, 0xc0000000, 8*1024*1024 ); - SET_BANK( 1, 0xc8000000, 8*1024*1024 ); - mi->nr_banks = 2; -#elif defined(CONFIG_SA1100_CERF_8MB) - SET_BANK( 0, 0xc0000000, 8*1024*1024 ); - mi->nr_banks = 1; -#else -#error "Undefined memory size for Cerfboard." -#endif - -// ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); -// setup_ramdisk(1, 0, 0, 8192); -// // Save 2Meg for RAMDisk -// setup_initrd(0xc0500000, 3*1024*1024); -} - static struct map_desc cerf_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Crystal Ethernet Chip */ @@ -96,7 +69,6 @@ MACHINE_START(CERF, "Intrinsyc's Cerf Family of Products") MAINTAINER("support@intrinsyc.com") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_cerf) MAPIO(cerf_map_io) INITIRQ(cerf_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/empeg.c b/arch/arm/mach-sa1100/empeg.c --- a/arch/arm/mach-sa1100/empeg.c Sun Jun 2 18:44:58 2002 +++ b/arch/arm/mach-sa1100/empeg.c Sun Jun 2 18:44:58 2002 @@ -15,20 +15,6 @@ #include "generic.h" - -static void __init -fixup_empeg(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 4*1024*1024 ); - SET_BANK( 1, 0xc8000000, 4*1024*1024 ); - mi->nr_banks = 2; - - ROOT_DEV = mk_kdev( 3, 1 ); /* /dev/hda1 */ - setup_ramdisk( 1, 0, 0, 4096 ); - setup_initrd( 0xd0000000+((1024-320)*1024), (320*1024) ); -} - static struct map_desc empeg_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash */ @@ -48,7 +34,6 @@ MACHINE_START(EMPEG, "empeg MP3 Car Audio Player") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_empeg) MAPIO(empeg_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/flexanet.c b/arch/arm/mach-sa1100/flexanet.c --- a/arch/arm/mach-sa1100/flexanet.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-sa1100/flexanet.c Sun Jun 2 18:44:57 2002 @@ -151,21 +151,6 @@ __initcall(flexanet_init); -static void __init -fixup_flexanet(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - /* fixed RAM size, by now (64MB) */ - SET_BANK( 0, 0xc0000000, 64*1024*1024 ); - mi->nr_banks = 1; - - /* setup ramdisk */ - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( 0xc0800000, 3*1024*1024 ); -} - - static struct map_desc flexanet_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xf0000000, 0x10000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* Board Control Register */ @@ -206,7 +191,6 @@ MACHINE_START(FLEXANET, "FlexaNet") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) BOOT_PARAMS(0xc0000100) - FIXUP(fixup_flexanet) MAPIO(flexanet_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/freebird.c b/arch/arm/mach-sa1100/freebird.c --- a/arch/arm/mach-sa1100/freebird.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/mach-sa1100/freebird.c Sun Jun 2 18:44:56 2002 @@ -51,19 +51,6 @@ __initcall(freebird_init); -static void __init -fixup_freebird(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ -#ifdef CONFIG_SA1100_FREEBIRD_OLD - SET_BANK( 0, 0xc0000000, 32*1024*1024 ); - mi->nr_banks = 1; - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0 ,0 , 8192 ); - setup_initrd( 0xc0800000, 3*1024*1024 ); -#endif -} - static struct map_desc freebird_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xf0000000, 0x12000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Board Control Register */ @@ -90,7 +77,6 @@ #ifdef CONFIG_SA1100_FREEBIRD_NEW BOOT_PARAMS(0xc0000100) #endif - FIXUP(fixup_freebird) MAPIO(freebird_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c --- a/arch/arm/mach-sa1100/generic.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-sa1100/generic.c Sun Jun 2 18:44:57 2002 @@ -78,7 +78,7 @@ static int __init sa11x0_init_clock(void) { - cpufreq_init(cclk_frequency_100khz[PPCR & 0xf] * 100); + cpufreq_init(cclk_frequency_100khz[PPCR & 0xf] * 100, 59000, 287000); return 0; } @@ -203,6 +203,3 @@ local_irq_restore(flags); } - -EXPORT_SYMBOL(sa1111_wake); -EXPORT_SYMBOL(sa1111_doze); diff -Nru a/arch/arm/mach-sa1100/graphicsclient.c b/arch/arm/mach-sa1100/graphicsclient.c --- a/arch/arm/mach-sa1100/graphicsclient.c Sun Jun 2 18:44:58 2002 +++ b/arch/arm/mach-sa1100/graphicsclient.c Sun Jun 2 18:44:58 2002 @@ -120,23 +120,6 @@ } -/* - * Initialization fixup - */ - -static void __init -fixup_graphicsclient(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 16*1024*1024 ); - SET_BANK( 1, 0xc8000000, 16*1024*1024 ); - mi->nr_banks = 2; - - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); -} - static struct map_desc graphicsclient_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xf0000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */ @@ -216,7 +199,6 @@ MACHINE_START(GRAPHICSCLIENT, "ADS GraphicsClient") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_graphicsclient) MAPIO(graphicsclient_map_io) INITIRQ(graphicsclient_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/graphicsmaster.c b/arch/arm/mach-sa1100/graphicsmaster.c --- a/arch/arm/mach-sa1100/graphicsmaster.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-sa1100/graphicsmaster.c Sun Jun 2 18:44:57 2002 @@ -152,24 +152,6 @@ } -/* - * Initialization fixup - */ - -static void __init -fixup_graphicsmaster(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 16*1024*1024 ); - mi->nr_banks = 1; - SET_BANK( 1, 0xc8000000, 16*1024*1024 ); - mi->nr_banks = 2; - - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); -} - static struct map_desc graphicsmaster_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xf0000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */ @@ -276,7 +258,6 @@ MACHINE_START(GRAPHICSMASTER, "ADS GraphicsMaster") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_graphicsmaster) MAPIO(graphicsmaster_map_io) INITIRQ(graphicsmaster_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/huw_webpanel.c b/arch/arm/mach-sa1100/huw_webpanel.c --- a/arch/arm/mach-sa1100/huw_webpanel.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-sa1100/huw_webpanel.c Sun Jun 2 18:44:57 2002 @@ -54,22 +54,6 @@ __initcall(init_huw_cs3); -static void __init -fixup_huw_webpanel(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - /** - memory information (JOR): - 32 MByte - 256KByte bootloader (init at boot time) - 32 kByte save area - **/ - SET_BANK( 0, 0xc0000000, ((32*1024 - (256 + 32)) * 1024)); - mi->nr_banks = 1; - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xc0800000), 8*1024*1024 ); -} - - /** memory information (JOR): 32 MByte - 256KByte bootloader (init at boot time) - 32 kByte save area @@ -95,7 +79,6 @@ MACHINE_START(HUW_WEBPANEL, "HuW-Webpanel") MAINTAINER("Roman Jordan") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_huw_webpanel) MAPIO(huw_webpanel_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/itsy.c b/arch/arm/mach-sa1100/itsy.c --- a/arch/arm/mach-sa1100/itsy.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-sa1100/itsy.c Sun Jun 2 18:44:57 2002 @@ -15,18 +15,6 @@ #include "generic.h" - -static void __init -fixup_itsy(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 16*1024*1024 ); - SET_BANK( 1, 0xc8000000, 16*1024*1024 ); - SET_BANK( 2, 0xd0000000, 16*1024*1024 ); - SET_BANK( 3, 0xd8000000, 16*1024*1024 ); - mi->nr_banks = 4; -} - /* BRADFIXME The egpio addresses aren't verifiably correct. (i.e. they're most likely wrong. */ static struct map_desc itsy_io_desc[] __initdata = { @@ -49,7 +37,6 @@ MACHINE_START(ITSY, "Compaq Itsy") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) BOOT_PARAMS(0xc0000100) - FIXUP(fixup_itsy) MAPIO(itsy_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c --- a/arch/arm/mach-sa1100/jornada720.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-sa1100/jornada720.c Sun Jun 2 18:44:57 2002 @@ -55,15 +55,6 @@ __initcall(jornada720_init); - -static void __init -fixup_jornada720(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 32*1024*1024 ); - mi->nr_banks = 1; -} - static struct map_desc jornada720_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xf0000000, 0x48000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Epson registers */ @@ -84,7 +75,6 @@ MACHINE_START(JORNADA720, "HP Jornada 720") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) BOOT_PARAMS(0xc0000100) - FIXUP(fixup_jornada720) MAPIO(jornada720_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c --- a/arch/arm/mach-sa1100/nanoengine.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/mach-sa1100/nanoengine.c Sun Jun 2 18:44:56 2002 @@ -15,20 +15,12 @@ #include "generic.h" - static void __init fixup_nanoengine(struct machine_desc *desc, struct tag *tags, char **cmdline, struct meminfo *mi) { - SET_BANK( 0, 0xc0000000, 32*1024*1024 ); - mi->nr_banks = 1; - - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); - /* Get command line parameters passed from the loader (if any) */ - if( *((char*)0xc0000100) ) + if (*((char*)0xc0000100)) *cmdline = ((char *)0xc0000100); } diff -Nru a/arch/arm/mach-sa1100/omnimeter.c b/arch/arm/mach-sa1100/omnimeter.c --- a/arch/arm/mach-sa1100/omnimeter.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/mach-sa1100/omnimeter.c Sun Jun 2 18:44:56 2002 @@ -40,18 +40,6 @@ __initcall(omnimeter_init); -static void __init -fixup_omnimeter(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 16*1024*1024 ); - mi->nr_banks = 1; - - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xd0000000), 0x00400000 ); -} - static struct map_desc omnimeter_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xd2000000, 0x10000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* TS */ @@ -69,7 +57,6 @@ MACHINE_START(OMNIMETER, "OmniMeter") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_omnimeter) MAPIO(omnimeter_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/pangolin.c b/arch/arm/mach-sa1100/pangolin.c --- a/arch/arm/mach-sa1100/pangolin.c Sun Jun 2 18:44:58 2002 +++ b/arch/arm/mach-sa1100/pangolin.c Sun Jun 2 18:44:58 2002 @@ -15,19 +15,6 @@ #include "generic.h" - -static void __init -fixup_pangolin(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 128*1024*1024 ); - mi->nr_banks = 1; - - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 16384 ); - setup_initrd( 0xc0800000, 3*1024*1024 ); -} - static struct map_desc pangolin_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */ @@ -52,7 +39,6 @@ MACHINE_START(PANGOLIN, "Dialogue-Pangolin") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_pangolin) MAPIO(pangolin_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/pfs168.c b/arch/arm/mach-sa1100/pfs168.c --- a/arch/arm/mach-sa1100/pfs168.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/mach-sa1100/pfs168.c Sun Jun 2 18:44:56 2002 @@ -55,19 +55,6 @@ set_GPIO_IRQ_edge(GPIO_UCB1300_IRQ, GPIO_RISING_EDGE); } - -static void __init -fixup_pfs168(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 16*1024*1024 ); - mi->nr_banks = 1; - - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( 0xc0800000, 3*1024*1024 ); -} - static struct map_desc pfs168_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */ @@ -98,10 +85,7 @@ MACHINE_START(PFS168, "Tulsa") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) -#if defined(CONFIG_PFS168_CMDLINE) BOOT_PARAMS(0xc0000100) -#endif - FIXUP(fixup_pfs168) MAPIO(pfs168_map_io) INITIRQ(pfs168_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c --- a/arch/arm/mach-sa1100/pleb.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-sa1100/pleb.c Sun Jun 2 18:44:57 2002 @@ -15,24 +15,6 @@ #include "generic.h" -static void __init -fixup_pleb(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK(0, 0xc0000000, 16*1024*1024); - SET_BANK(1, 0xc8000000, 16*1024*1024); - SET_BANK(2, 0xd0000000, 16*1024*1024); - SET_BANK(3, 0xd8000000, 16*1024*1024); - - /* make this 4 a second memory card is used to make 64MB */ - /* make it 1 if a 16MB memory card is used */ - mi->nr_banks = 2; /* Default 32MB */ - - ROOT_DEV = mk_kdev(RAMDISK_MAJOR, 0); - setup_ramdisk(1, 0, 0, 8192); - setup_initrd(0xc0400000, 4*1024*1024); -} - static struct map_desc pleb_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xe8000000, 0x00000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* main flash memory */ @@ -55,7 +37,6 @@ MACHINE_START(PLEB, "PLEB") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_pleb) MAPIO(pleb_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/sherman.c b/arch/arm/mach-sa1100/sherman.c --- a/arch/arm/mach-sa1100/sherman.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/mach-sa1100/sherman.c Sun Jun 2 18:44:56 2002 @@ -15,20 +15,6 @@ #include "generic.h" - -static void __init -fixup_sherman(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 64*1024*1024 ); - SET_BANK( 1, 0xc8000000, 64*1024*1024 ); - mi->nr_banks = 2; - - ROOT_DEV = mk_kdev( 60, 2 ); - setup_ramdisk( 1, 0, 0, 8192 ); -// setup_initrd( 0xc0400000, 8*1024*1024 ); -} - static void __init sherman_map_io(void) { sa1100_map_io(); @@ -39,7 +25,6 @@ MACHINE_START(SHERMAN, "Blazie Engineering Sherman") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_sherman) MAPIO(sherman_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c --- a/arch/arm/mach-sa1100/simpad.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/mach-sa1100/simpad.c Sun Jun 2 18:44:56 2002 @@ -40,22 +40,6 @@ *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow; } -static void __init -fixup_simpad(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ -#ifdef CONFIG_SA1100_SIMPAD_DRAM_64MB /* DRAM */ - SET_BANK( 0, 0xc0000000, 64*1024*1024 ); -#else - SET_BANK( 0, 0xc0000000, 32*1024*1024 ); -#endif - mi->nr_banks = 1; - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); -} - - static struct map_desc simpad_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */ @@ -141,22 +125,14 @@ } -static struct proc_dir_entry *proc_cs3; - static int __init cs3_init(void) { - proc_cs3 = create_proc_entry("cs3", 0, 0); + struct proc_dir_entry *proc_cs3 = create_proc_entry("cs3", 0, 0); if (proc_cs3) proc_cs3->read_proc = proc_cs3_read; return 0; } -static int __exit cs3_exit(void) -{ - if (proc_cs3) - remove_proc_entry( "cs3", 0); - return 0; -} __initcall(cs3_init); #endif // CONFIG_PROC_FS @@ -164,7 +140,6 @@ MACHINE_START(SIMPAD, "Simpad") MAINTAINER("Juergen Messerer") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_simpad) MAPIO(simpad_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c --- a/arch/arm/mach-sa1100/system3.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-sa1100/system3.c Sun Jun 2 18:44:57 2002 @@ -73,8 +73,6 @@ */ /* init funcs */ -static void __init fixup_system3(struct machine_desc *desc, - struct tag *tags, char **cmdline, struct meminfo *mi); static int __init system3_init(void); static void __init system3_init_irq(void); static void __init system3_map_io(void); @@ -229,25 +227,6 @@ } /** - * fixup_system3 - fixup function for system 3 board - * @desc: machine description - * @param: kernel params - * @cmdline: kernel cmdline - * @mi: memory info struct - * - */ -static void __init fixup_system3(struct machine_desc *desc, - struct tag *tags, char **cmdline, struct meminfo *mi) -{ - DPRINTK( "%s\n", "START" ); - - ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( 0xc0800000, 8*1024*1024 ); -} - - -/** * system3_uart_pm - powermgmt callback function for system 3 UART * @port: uart port structure * @state: pm state @@ -457,7 +436,6 @@ MACHINE_START(PT_SYSTEM3, "PT System 3") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) BOOT_PARAMS(0xc0000100) - FIXUP(fixup_system3) MAPIO(system3_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mach-sa1100/victor.c b/arch/arm/mach-sa1100/victor.c --- a/arch/arm/mach-sa1100/victor.c Sun Jun 2 18:44:56 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,80 +0,0 @@ -/* - * linux/arch/arm/mach-sa1100/victor.c - * - * Author: Nicolas Pitre - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "generic.h" - - -static void victor_power_off(void) -{ - /* switch off power supply */ - mdelay(2000); - GPCR = GPIO_GPIO23; - while (1); -} - -static int __init victor_init(void) -{ - pm_power_off = victor_power_off; - return 0; -} - -__initcall(victor_init); - - -static void __init -fixup_victor(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 4*1024*1024 ); - mi->nr_banks = 1; - - ROOT_DEV = mk_kdev( 60, 2 ); - - /* Get command line parameters passed from the loader (if any) */ - if( *((char*)0xc0000000) ) - strcpy( *cmdline, ((char *)0xc0000000) ); - - /* power off if any problem */ - strcat( *cmdline, " panic=1" ); -} - -static struct map_desc victor_io_desc[] __initdata = { - /* virtual physical length domain r w c b */ - { 0xe8000000, 0x00000000, 0x00200000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash */ - LAST_DESC -}; - -static void __init victor_map_io(void) -{ - sa1100_map_io(); - iotable_init(victor_io_desc); - - sa1100_register_uart(0, 3); -} - -MACHINE_START(VICTOR, "VisuAide Victor") - BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_victor) - MAPIO(victor_map_io) - INITIRQ(sa1100_init_irq) -MACHINE_END diff -Nru a/arch/arm/mach-sa1100/xp860.c b/arch/arm/mach-sa1100/xp860.c --- a/arch/arm/mach-sa1100/xp860.c Sun Jun 2 18:44:57 2002 +++ b/arch/arm/mach-sa1100/xp860.c Sun Jun 2 18:44:57 2002 @@ -56,15 +56,6 @@ __initcall(xp860_init); - -static void __init -fixup_xp860(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ - SET_BANK( 0, 0xc0000000, 32*1024*1024 ); - mi->nr_banks = 1; -} - static struct map_desc xp860_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xf0000000, 0x10000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCSI */ @@ -84,7 +75,6 @@ MACHINE_START(XP860, "XP860") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - FIXUP(fixup_xp860) MAPIO(xp860_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm/mm/init.c b/arch/arm/mm/init.c --- a/arch/arm/mm/init.c Sun Jun 2 18:44:56 2002 +++ b/arch/arm/mm/init.c Sun Jun 2 18:44:56 2002 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,8 @@ #endif #define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(pte_t)) + +mmu_gather_t mmu_gathers[NR_CPUS]; extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern char _stext, _text, _etext, _end, __init_begin, __init_end; diff -Nru a/arch/cris/drivers/ide.c b/arch/cris/drivers/ide.c --- a/arch/cris/drivers/ide.c Sun Jun 2 18:44:56 2002 +++ b/arch/cris/drivers/ide.c Sun Jun 2 18:44:56 2002 @@ -688,17 +688,16 @@ /* * etrax_dma_intr() is the handler for disk read/write DMA interrupts */ -static ide_startstop_t etrax_dma_intr (struct ata_device *drive, struct request *rq) +static ide_startstop_t etrax_dma_intr(struct ata_device *drive, struct request *rq) { int i, dma_stat; - byte stat; LED_DISK_READ(0); LED_DISK_WRITE(0); dma_stat = drive->channel->udma(ide_dma_end, drive, rq); - stat = GET_STAT(); /* get drive status */ - if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { + /* get drive status */ + if (ata_status(drive, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) { if (!dma_stat) { for (i = rq->nr_sectors; i > 0;) { i -= rq->current_nr_sectors; @@ -708,7 +707,7 @@ } printk("%s: bad DMA status\n", drive->name); } - return ide_error(drive, "dma_intr", stat); + return ata_error(drive, __FUNCTION__); } /* diff -Nru a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c --- a/arch/i386/kernel/acpi.c Sun Jun 2 18:44:58 2002 +++ b/arch/i386/kernel/acpi.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /* * acpi.c - Architecture-Specific Low-Level ACPI Support * - * Copyright (C) 2001 Paul Diefenbaugh + * Copyright (C) 2001, 2002 Paul Diefenbaugh * Copyright (C) 2001 Jun Nakajima * Copyright (C) 2001 Patrick Mochel * @@ -44,16 +44,10 @@ #include #include #include -#define ACPI_C -#include #define PREFIX "ACPI: " -extern struct acpi_boot_flags acpi_boot; - -int acpi_mp_config = 0; - /* -------------------------------------------------------------------------- Boot-time Configuration @@ -61,6 +55,9 @@ #ifdef CONFIG_ACPI_BOOT +enum acpi_irq_model_id acpi_irq_model; + + /* * Use reserved fixmap pages for physical-to-virtual mappings of ACPI tables. * Note that the same range is used for each table, so tables that need to @@ -106,65 +103,58 @@ #ifdef CONFIG_X86_LOCAL_APIC -static int total_cpus __initdata = 0; +int acpi_lapic; -/* From mpparse.c */ -extern void __init MP_processor_info(struct mpc_config_processor *); -extern void __init MP_ioapic_info (struct mpc_config_ioapic *); -extern void __init MP_lintsrc_info(struct mpc_config_lintsrc *); +static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; -int __init -acpi_parse_lapic ( - acpi_table_entry_header *header) + +static int __init +acpi_parse_madt ( + unsigned long phys_addr, + unsigned long size) { - struct acpi_table_lapic *cpu = NULL; - struct mpc_config_processor processor; + struct acpi_table_madt *madt = NULL; - cpu = (struct acpi_table_lapic*) header; - if (!cpu) + if (!phys_addr || !size) return -EINVAL; - acpi_table_print_madt_entry(header); - - if (!cpu->flags.enabled) { - printk(KERN_INFO "Processor #%d disabled\n", cpu->id); - return 0; - } - - if (cpu->id >= MAX_APICS) { - printk(KERN_WARNING "Processor #%d invalid (max %d)\n", - cpu->id, MAX_APICS); + madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size); + if (!madt) { + printk(KERN_WARNING PREFIX "Unable to map MADT\n"); return -ENODEV; } - /* - * Fill in the info we want to save. Not concerned about - * the processor ID. Processor features aren't present in - * the table. - */ - processor.mpc_type = MP_PROCESSOR; - processor.mpc_apicid = cpu->id; - processor.mpc_cpuflag = CPU_ENABLED; - if (cpu->id == boot_cpu_physical_apicid) { - /* TBD: Circular reference trying to establish BSP */ - processor.mpc_cpuflag |= CPU_BOOTPROCESSOR; - } - processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) - | (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask; - processor.mpc_featureflag = boot_cpu_data.x86_capability[0]; - processor.mpc_reserved[0] = 0; - processor.mpc_reserved[1] = 0; - processor.mpc_apicver = 0x10; /* Integrated APIC */ + if (madt->lapic_address) + acpi_lapic_addr = (u64) madt->lapic_address; + + printk(KERN_INFO PREFIX "Local APIC address 0x%08x\n", + madt->lapic_address); - MP_processor_info(&processor); + return 0; +} - total_cpus++; + +static int __init +acpi_parse_lapic ( + acpi_table_entry_header *header) +{ + struct acpi_table_lapic *processor = NULL; + + processor = (struct acpi_table_lapic*) header; + if (!processor) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + mp_register_lapic ( + processor->id, /* APIC ID */ + processor->flags.enabled); /* Enabled? */ return 0; } -int __init +static int __init acpi_parse_lapic_addr_ovr ( acpi_table_entry_header *header) { @@ -174,118 +164,80 @@ if (!lapic_addr_ovr) return -EINVAL; - /* TBD: Support local APIC address override entries */ + acpi_lapic_addr = lapic_addr_ovr->address; return 0; } -int __init +static int __init acpi_parse_lapic_nmi ( acpi_table_entry_header *header) { - struct acpi_table_lapic_nmi *lacpi_nmi = NULL; + struct acpi_table_lapic_nmi *lapic_nmi = NULL; - lacpi_nmi = (struct acpi_table_lapic_nmi*) header; - if (!lacpi_nmi) + lapic_nmi = (struct acpi_table_lapic_nmi*) header; + if (!lapic_nmi) return -EINVAL; acpi_table_print_madt_entry(header); - /* TBD: Support lapic_nmi entries */ + if (lapic_nmi->lint != 1) + printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n"); return 0; } #endif /*CONFIG_X86_LOCAL_APIC*/ - #ifdef CONFIG_X86_IO_APIC -int __init +int acpi_ioapic; + +static int __init acpi_parse_ioapic ( acpi_table_entry_header *header) { struct acpi_table_ioapic *ioapic = NULL; - /* - struct mpc_config_ioapic mp_ioapic; - struct IO_APIC_reg_01 reg_01; - */ ioapic = (struct acpi_table_ioapic*) header; if (!ioapic) return -EINVAL; acpi_table_print_madt_entry(header); - - /* - * Cobble up an entry for the IOAPIC (just as we do for LAPIC entries). - * Note that we aren't doing anything with ioapic->vector, and - * mpc_apicver gets read directly from ioapic. - */ - - /* - * TBD: Complete I/O APIC support. - * - mp_ioapic.mpc_type = MP_IOAPIC; - mp_ioapic.mpc_apicid = ioapic->id; - mp_ioapic.mpc_flags = MPC_APIC_USABLE; - mp_ioapic.mpc_apicaddr = ioapic->address; - set_fixmap_nocache(nr_ioapics + FIX_IO_APIC_BASE_0, - mp_ioapic.mpc_apicaddr); - - printk("mapped IOAPIC to %08lx (%08lx)\n", - __fix_to_virt(nr_ioapics), mp_ioapic.mpc_apicaddr); - - *(int *)®_01 = io_apic_read(nr_ioapics, 1); - mp_ioapic.mpc_apicver = reg_01.version; - MP_ioapic_info(&mp_ioapic); - */ + mp_register_ioapic ( + ioapic->id, + ioapic->address, + ioapic->global_irq_base); + return 0; } -int __init +static int __init acpi_parse_int_src_ovr ( acpi_table_entry_header *header) { - struct acpi_table_int_src_ovr *int_src_ovr = NULL; - /* - struct mpc_config_intsrc my_intsrc; - int i = 0; - */ + struct acpi_table_int_src_ovr *intsrc = NULL; - int_src_ovr = (struct acpi_table_int_src_ovr*) header; - if (!int_src_ovr) + intsrc = (struct acpi_table_int_src_ovr*) header; + if (!intsrc) return -EINVAL; acpi_table_print_madt_entry(header); - /* - * TBD: Complete I/O APIC support. - * - my_intsrc.mpc_type = MP_INTSRC; - my_intsrc.mpc_irqtype = mp_INT; - my_intsrc.mpc_irqflag = *(unsigned short*)(&(int_src_ovr->flags)); - my_intsrc.mpc_srcbus = int_src_ovr->bus; - my_intsrc.mpc_srcbusirq = int_src_ovr->bus_irq; - my_intsrc.mpc_dstapic = 0; - my_intsrc.mpc_dstirq = int_src_ovr->global_irq; - - for (i = 0; i < mp_irq_entries; i++) { - if (mp_irqs[i].mpc_srcbusirq == my_intsrc.mpc_srcbusirq) { - mp_irqs[i] = my_intsrc; - break; - } - } - */ + mp_override_legacy_irq ( + intsrc->bus_irq, + intsrc->flags.polarity, + intsrc->flags.trigger, + intsrc->global_irq); return 0; } -int __init +static int __init acpi_parse_nmi_src ( acpi_table_entry_header *header) { @@ -297,45 +249,14 @@ acpi_table_print_madt_entry(header); - /* TBD: Support nimsrc entries */ + /* TBD: Support nimsrc entries? */ return 0; } - #endif /*CONFIG_X86_IO_APIC*/ -int __init -acpi_parse_madt ( - unsigned long phys_addr, - unsigned long size) -{ - struct acpi_table_madt *madt = NULL; - - if (!phys_addr || !size) - return -EINVAL; - - madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size); - if (!madt) { - printk(KERN_WARNING PREFIX "Unable to map MADT\n"); - return -ENODEV; - } - -#ifdef CONFIG_X86_LOCAL_APIC - if (madt->lapic_address) - mp_lapic_addr = madt->lapic_address; - else - mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; -#endif /*CONFIG_X86_LOCAL_APIC*/ - - printk(KERN_INFO PREFIX "Local APIC address 0x%08x\n", - madt->lapic_address); - - return 0; -} - - static unsigned long __init acpi_scan_rsdp ( unsigned long start, @@ -349,7 +270,7 @@ * RSDP signature. */ for (offset = 0; offset < length; offset += 16) { - if (0 != strncmp((char *) (start + offset), "RSD PTR ", sig_len)) + if (strncmp((char *) (start + offset), "RSD PTR ", sig_len)) continue; return (start + offset); } @@ -358,25 +279,20 @@ } -int __init -acpi_find_rsdp ( - unsigned long *rsdp_phys) +unsigned long __init +acpi_find_rsdp (void) { - if (!rsdp_phys) - return -EINVAL; + unsigned long rsdp_phys = 0; /* * Scan memory looking for the RSDP signature. First search EBDA (low * memory) paragraphs and then search upper memory (E0000-FFFFF). */ - (*rsdp_phys) = acpi_scan_rsdp (0, 0x400); - if (!(*rsdp_phys)) - (*rsdp_phys) = acpi_scan_rsdp (0xE0000, 0xFFFFF); - - if (!(*rsdp_phys)) - return -ENODEV; + rsdp_phys = acpi_scan_rsdp (0, 0x400); + if (!rsdp_phys) + rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF); - return 0; + return rsdp_phys; } @@ -386,13 +302,20 @@ { int result = 0; - /* Initialize the ACPI boot-time table parser */ + /* + * The default interrupt routing model is PIC (8259). This gets + * overriden if IOAPICs are enumerated (below). + */ + acpi_irq_model = ACPI_IRQ_MODEL_PIC; + + /* + * Initialize the ACPI boot-time table parser. + */ result = acpi_table_init(cmdline); - if (0 != result) + if (result) return result; #ifdef CONFIG_X86_LOCAL_APIC -#ifdef CONFIG_X86_IO_APIC /* * MADT @@ -402,86 +325,100 @@ * information -- the successor to MPS tables. */ - if (!acpi_boot.madt) { - printk(KERN_INFO PREFIX "MADT parsing disabled via command-line\n"); - return 0; - } - result = acpi_table_parse(ACPI_APIC, acpi_parse_madt); - if (0 == result) { + if (!result) { printk(KERN_WARNING PREFIX "MADT not present\n"); return 0; } - else if (0 > result) { + else if (result < 0) { printk(KERN_ERR PREFIX "Error parsing MADT\n"); return result; } - else if (1 < result) + else if (result > 1) printk(KERN_WARNING PREFIX "Multiple MADT tables exist\n"); - /* Local APIC */ + /* + * Local APIC + * ---------- + * Note that the LAPIC address is obtained from the MADT (32-bit value) + * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value). + */ result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr); - if (0 > result) { + if (result < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); return result; } + mp_register_lapic_address(acpi_lapic_addr); + result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic); - if (1 > result) { - printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries!\n"); + if (!result) { + printk(KERN_ERR PREFIX "No LAPIC entries present\n"); + /* TBD: Cleanup to allow fallback to MPS */ return -ENODEV; } + else if (result < 0) { + printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return result; + } result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi); - if (0 > result) { + if (result < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ return result; } - /* I/O APIC */ + acpi_lapic = 1; + +#endif /*CONFIG_X86_LOCAL_APIC*/ + +#ifdef CONFIG_X86_IO_APIC + + /* + * I/O APIC + * -------- + */ result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic); - if (1 > result) { - printk(KERN_ERR PREFIX "Error parsing MADT - no IOAPIC entries!\n"); + if (!result) { + printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); return -ENODEV; } + else if (result < 0) { + printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n"); + return result; + } - acpi_mp_config = 1; - - /* - * TBD: Complete I/O APIC support. - * - construct_default_ACPI_table(); - */ + /* Build a default routing table for legacy (ISA) interrupts. */ + mp_config_acpi_legacy_irqs(); result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr); - if (0 > result) { + if (result < 0) { printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ return result; } result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src); - if (0 > result) { + if (result < 0) { printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ return result; } - /* Make boot-up look pretty */ - printk("%d CPUs total\n", total_cpus); + acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; + + acpi_ioapic = 1; #endif /*CONFIG_X86_IO_APIC*/ -#endif /*CONFIG_X86_LOCAL_APIC*/ -#ifdef CONFIG_SERIAL_ACPI - /* - * TBD: Need phased approach to table parsing (only do those absolutely - * required during boot-up). Recommend expanding concept of fix- - * feature devices (ACPI Bus driver) to include table-based devices - * such as serial ports, EC, SMBus, etc. - */ - /* acpi_table_parse(ACPI_SPCR, acpi_parse_spcr);*/ -#endif /*CONFIG_SERIAL_ACPI*/ +#ifdef CONFIG_X86_LOCAL_APIC + if (acpi_lapic && acpi_ioapic) + smp_found_config = 1; +#endif return 0; } @@ -489,23 +426,6 @@ #endif /*CONFIG_ACPI_BOOT*/ -int __init -acpi_get_interrupt_model ( - int *type) -{ - if (!type) - return -EINVAL; - -#ifdef CONFIG_X86_IO_APIC - *type = ACPI_INT_MODEL_IOAPIC; -#else - *type = ACPI_INT_MODEL_PIC; -#endif - - return 0; -} - - /* -------------------------------------------------------------------------- Low-Level Sleep Support -------------------------------------------------------------------------- */ @@ -625,33 +545,4 @@ printk(KERN_DEBUG "ACPI: have wakeup address 0x%8.8lx\n", acpi_wakeup_address); } -/* - * (KG): Since we affect stack here, we make this function as flat and easy - * as possible in order to not provoke gcc to use local variables on the stack. - * Note that on resume, all (expect nosave) variables will have the state from - * the time of writing (suspend_save_image) and the registers (including the - * stack pointer, but excluding the instruction pointer) will be loaded with - * the values saved at save_processor_context() time. - */ -void do_suspend_magic(int resume) -{ - /* DANGER WILL ROBINSON! - * - * If this function is too difficult for gcc to optimize, it will crash and burn! - * see above. - * - * DO NOT TOUCH. - */ - if (!resume) { - save_processor_context(); - acpi_save_register_state((unsigned long)&&acpi_sleep_done); - acpi_enter_sleep_state(3); - return; - } -acpi_sleep_done: - restore_processor_context(); - printk("CPU context restored...\n"); -} - #endif /*CONFIG_ACPI_SLEEP*/ - diff -Nru a/arch/i386/kernel/acpi_wakeup.S b/arch/i386/kernel/acpi_wakeup.S --- a/arch/i386/kernel/acpi_wakeup.S Sun Jun 2 18:44:56 2002 +++ b/arch/i386/kernel/acpi_wakeup.S Sun Jun 2 18:44:56 2002 @@ -179,7 +179,7 @@ rep lodsb movw $0x0e00 + 'O', %ds:(0xb8018) - movl %cs:saved_magic2, %eax + movl %cs:saved_magic, %eax cmpl $0x12345678, %eax jne bogus_magic @@ -243,7 +243,7 @@ movl saved_videomode, %edx movl %edx, video_mode - wakeup_start (%eax) movl $0x12345678, real_magic - wakeup_start (%eax) - movl $0x12345678, saved_magic2 + movl $0x12345678, saved_magic # restore the regs we used popl %edi @@ -261,7 +261,6 @@ ENTRY(saved_esp) .long 0 ENTRY(saved_magic) .long 0 -ENTRY(saved_magic2) .long 0 ALIGN # saved registers diff -Nru a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c --- a/arch/i386/kernel/apm.c Sun Jun 2 18:44:56 2002 +++ b/arch/i386/kernel/apm.c Sun Jun 2 18:44:56 2002 @@ -1792,7 +1792,7 @@ idle_threshold = simple_strtol(str + 15, NULL, 0); if ((strncmp(str, "idle-period=", 12) == 0) || (strncmp(str, "idle_period=", 12) == 0)) - idle_threshold = simple_strtol(str + 15, NULL, 0); + idle_period = simple_strtol(str + 12, NULL, 0); invert = (strncmp(str, "no-", 3) == 0) || (strncmp(str, "no_", 3) == 0); if (invert) diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Sun Jun 2 18:44:57 2002 +++ b/arch/i386/kernel/io_apic.c Sun Jun 2 18:44:57 2002 @@ -17,6 +17,7 @@ * thanks to Eric Gilmore * and Rolf G. Tews * for testing these extensively + * Paul Diefenbaugh : Added full ACPI support */ #include @@ -29,6 +30,7 @@ #include #include #include +#include #include #include @@ -1111,6 +1113,10 @@ unsigned char old_id; unsigned long flags; + if (acpi_ioapic) + /* This gets done during IOAPIC enumeration for ACPI. */ + return; + if (clustered_apic_mode) /* We don't have a good way to do this yet - hack */ phys_id_present_map = (u_long) 0xf; @@ -1699,8 +1705,7 @@ printk("ENABLING IO-APIC IRQs\n"); /* - * Set up the IO-APIC IRQ routing table by parsing the MP-BIOS - * mptable: + * Set up IO-APIC IRQ routing. */ setup_ioapic_ids_from_mpc(); sync_Arb_IDs(); @@ -1709,3 +1714,159 @@ check_timer(); print_IO_APIC(); } + + +/* -------------------------------------------------------------------------- + ACPI-based IOAPIC Configuration + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_BOOT + +#define IO_APIC_MAX_ID 15 + +int __init io_apic_get_unique_id (int ioapic, int apic_id) +{ + struct IO_APIC_reg_00 reg_00; + static unsigned long apic_id_map = 0; + unsigned long flags; + int i = 0; + + /* + * The P4 platform supports up to 256 APIC IDs on two separate APIC + * buses (one for LAPICs, one for IOAPICs), where predecessors only + * supports up to 16 on one shared APIC bus. + * + * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full + * advantage of new APIC bus architecture. + */ + + if (!apic_id_map) + apic_id_map = phys_cpu_present_map; + + spin_lock_irqsave(&ioapic_lock, flags); + *(int *)®_00 = io_apic_read(ioapic, 0); + spin_unlock_irqrestore(&ioapic_lock, flags); + + if (apic_id >= IO_APIC_MAX_ID) { + printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " + "%d\n", ioapic, apic_id, reg_00.ID); + apic_id = reg_00.ID; + } + + /* + * Every APIC in a system must have a unique ID or we get lots of nice + * 'stuck on smp_invalidate_needed IPI wait' messages. + */ + if (apic_id_map & (1 << apic_id)) { + + for (i = 0; i < IO_APIC_MAX_ID; i++) { + if (!(apic_id_map & (1 << i))) + break; + } + + if (i == IO_APIC_MAX_ID) + panic("Max apic_id exceeded!\n"); + + printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, " + "trying %d\n", ioapic, apic_id, i); + + apic_id = i; + } + + apic_id_map |= (1 << apic_id); + + if (reg_00.ID != apic_id) { + reg_00.ID = apic_id; + + spin_lock_irqsave(&ioapic_lock, flags); + io_apic_write(ioapic, 0, *(int *)®_00); + *(int *)®_00 = io_apic_read(ioapic, 0); + spin_unlock_irqrestore(&ioapic_lock, flags); + + /* Sanity check */ + if (reg_00.ID != apic_id) + panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); + } + + printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); + + return apic_id; +} + + +int __init io_apic_get_version (int ioapic) +{ + struct IO_APIC_reg_01 reg_01; + unsigned long flags; + + spin_lock_irqsave(&ioapic_lock, flags); + *(int *)®_01 = io_apic_read(ioapic, 1); + spin_unlock_irqrestore(&ioapic_lock, flags); + + return reg_01.version; +} + + +int __init io_apic_get_redir_entries (int ioapic) +{ + struct IO_APIC_reg_01 reg_01; + unsigned long flags; + + spin_lock_irqsave(&ioapic_lock, flags); + *(int *)®_01 = io_apic_read(ioapic, 1); + spin_unlock_irqrestore(&ioapic_lock, flags); + + return reg_01.entries; +} + + +int io_apic_set_pci_routing (int ioapic, int pin, int irq) +{ + struct IO_APIC_route_entry entry; + unsigned long flags; + + if (!IO_APIC_IRQ(irq)) { + printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0/n", + ioapic); + return -EINVAL; + } + + /* + * Generate a PCI IRQ routing entry and program the IOAPIC accordingly. + * Note that we mask (disable) IRQs now -- these get enabled when the + * corresponding device driver registers for this IRQ. + */ + + memset(&entry,0,sizeof(entry)); + + entry.delivery_mode = dest_LowestPrio; + entry.dest_mode = INT_DELIVERY_MODE; + entry.dest.logical.logical_dest = TARGET_CPUS; + entry.mask = 1; /* Disabled (masked) */ + entry.trigger = 1; /* Level sensitive */ + entry.polarity = 1; /* Low active */ + + add_pin_to_irq(irq, ioapic, pin); + + entry.vector = assign_irq_vector(irq); + + printk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> " + "IRQ %d)\n", ioapic, + mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq); + + irq_desc[irq].handler = &ioapic_level_irq_type; + + set_intr_gate(entry.vector, interrupt[irq]); + + if (!ioapic && (irq < 16)) + disable_8259A_irq(irq); + + spin_lock_irqsave(&ioapic_lock, flags); + io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1)); + io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0)); + spin_unlock_irqrestore(&ioapic_lock, flags); + + return entry.vector; +} + +#endif /*CONFIG_ACPI_BOOT*/ diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c --- a/arch/i386/kernel/mpparse.c Sun Jun 2 18:44:57 2002 +++ b/arch/i386/kernel/mpparse.c Sun Jun 2 18:44:57 2002 @@ -9,12 +9,14 @@ * Erich Boleyn : MP v1.4 and additional changes. * Alan Cox : Added EBDA scanning * Ingo Molnar : various cleanups and rewrites - * Maciej W. Rozycki : Bits for default MP configurations + * Maciej W. Rozycki: Bits for default MP configurations + * Paul Diefenbaugh: Added full ACPI support */ #include #include #include +#include #include #include #include @@ -27,6 +29,7 @@ #include #include #include +#include /* Have we found an MP table */ int smp_found_config; @@ -426,10 +429,10 @@ printk("APIC at: 0x%lX\n",mpc->mpc_lapic); /* - * Save the local APIC address (it might be non-default), but only - * if we're not using the ACPI tables. + * Save the local APIC address (it might be non-default) -- but only + * if we're not using ACPI. */ - if (!acpi_mp_config) + if (!acpi_lapic) mp_lapic_addr = mpc->mpc_lapic; if (clustered_apic_mode && mpc->mpc_oemptr) { @@ -448,9 +451,8 @@ { struct mpc_config_processor *m= (struct mpc_config_processor *)mpt; - - /* ACPI may already have provided this one for us */ - if (!acpi_mp_config) + /* ACPI may have already provided this data */ + if (!acpi_lapic) MP_processor_info(m); mpt += sizeof(*m); count += sizeof(*m); @@ -672,6 +674,19 @@ { struct intel_mp_floating *mpf = mpf_found; + /* + * ACPI may be used to obtain the entire SMP configuration or just to + * enumerate/configure processors (CONFIG_ACPI_HT_ONLY). Note that + * ACPI supports both logical (e.g. Hyper-Threading) and physical + * processors, where MPS only supports physical. + */ + if (acpi_lapic && acpi_ioapic) { + printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n"); + return; + } + else if (acpi_lapic) + printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n"); + printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); if (mpf->mpf_feature2 & (1<<7)) { printk(" IMCR and PIC compatibility mode.\n"); @@ -834,3 +849,315 @@ #endif } + +/* -------------------------------------------------------------------------- + ACPI-based MP Configuration + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_BOOT + +void __init mp_register_lapic_address ( + u64 address) +{ + mp_lapic_addr = (unsigned long) address; + + set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); + + if (boot_cpu_physical_apicid == -1U) + boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); + + Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid); +} + + +void __init mp_register_lapic ( + u8 id, + u8 enabled) +{ + struct mpc_config_processor processor; + int boot_cpu = 0; + + if (id >= MAX_APICS) { + printk(KERN_WARNING "Processor #%d invalid (max %d)\n", + id, MAX_APICS); + return; + } + + if (id == boot_cpu_physical_apicid) + boot_cpu = 1; + + processor.mpc_type = MP_PROCESSOR; + processor.mpc_apicid = id; + processor.mpc_apicver = 0x10; /* TBD: lapic version */ + processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0); + processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0); + processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | + (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask; + processor.mpc_featureflag = boot_cpu_data.x86_capability[0]; + processor.mpc_reserved[0] = 0; + processor.mpc_reserved[1] = 0; + + MP_processor_info(&processor); +} + +#ifdef CONFIG_X86_IO_APIC + +#define MP_ISA_BUS 0 +#define MP_MAX_IOAPIC_PIN 127 + +struct mp_ioapic_routing { + int apic_id; + int irq_start; + int irq_end; + u32 pin_programmed[4]; +} mp_ioapic_routing[MAX_IO_APICS]; + + +static int __init mp_find_ioapic ( + int irq) +{ + int i = 0; + + /* Find the IOAPIC that manages this IRQ. */ + for (i = 0; i < nr_ioapics; i++) { + if ((irq >= mp_ioapic_routing[i].irq_start) + && (irq <= mp_ioapic_routing[i].irq_end)) + return i; + } + + printk(KERN_ERR "ERROR: Unable to locate IOAPIC for IRQ %d/n", irq); + + return -1; +} + + +void __init mp_register_ioapic ( + u8 id, + u32 address, + u32 irq_base) +{ + int idx = 0; + + if (nr_ioapics >= MAX_IO_APICS) { + printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " + "(found %d)\n", MAX_IO_APICS, nr_ioapics); + panic("Recompile kernel with bigger MAX_IO_APICS!\n"); + } + if (!address) { + printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address" + " found in MADT table, skipping!\n"); + return; + } + + idx = nr_ioapics++; + + mp_ioapics[idx].mpc_type = MP_IOAPIC; + mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE; + mp_ioapics[idx].mpc_apicaddr = address; + + set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); + mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id); + mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); + + /* + * Build basic IRQ lookup table to facilitate irq->io_apic lookups + * and to prevent reprogramming of IOAPIC pins (PCI IRQs). + */ + mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid; + mp_ioapic_routing[idx].irq_start = irq_base; + mp_ioapic_routing[idx].irq_end = irq_base + + io_apic_get_redir_entries(idx); + + printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, " + "IRQ %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, + mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, + mp_ioapic_routing[idx].irq_start, + mp_ioapic_routing[idx].irq_end); + + return; +} + + +void __init mp_override_legacy_irq ( + u8 bus_irq, + u8 polarity, + u8 trigger, + u32 global_irq) +{ + struct mpc_config_intsrc intsrc; + int i = 0; + int found = 0; + int ioapic = -1; + int pin = -1; + + /* + * Convert 'global_irq' to 'ioapic.pin'. + */ + ioapic = mp_find_ioapic(global_irq); + if (ioapic < 0) + return; + pin = global_irq - mp_ioapic_routing[ioapic].irq_start; + + /* + * TBD: This check is for faulty timer entries, where the override + * erroneously sets the trigger to level, resulting in a HUGE + * increase of timer interrupts! + */ + if ((bus_irq == 0) && (global_irq == 2) && (trigger == 3)) + trigger = 1; + + intsrc.mpc_type = MP_INTSRC; + intsrc.mpc_irqtype = mp_INT; + intsrc.mpc_irqflag = (trigger << 2) | polarity; + intsrc.mpc_srcbus = MP_ISA_BUS; + intsrc.mpc_srcbusirq = bus_irq; /* IRQ */ + intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */ + intsrc.mpc_dstirq = pin; /* INTIN# */ + + Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n", + intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, + (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, + intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq); + + /* + * If an existing [IOAPIC.PIN -> IRQ] routing entry exists we override it. + * Otherwise create a new entry (e.g. global_irq == 2). + */ + for (i = 0; i < mp_irq_entries; i++) { + if ((mp_irqs[i].mpc_dstapic == intsrc.mpc_dstapic) + && (mp_irqs[i].mpc_dstirq == intsrc.mpc_dstirq)) { + mp_irqs[i] = intsrc; + found = 1; + break; + } + } + if (!found) { + mp_irqs[mp_irq_entries] = intsrc; + if (++mp_irq_entries == MAX_IRQ_SOURCES) + panic("Max # of irq sources exceeded!\n"); + } + + return; +} + + +void __init mp_config_acpi_legacy_irqs (void) +{ + struct mpc_config_intsrc intsrc; + int i = 0; + int ioapic = -1; + + /* + * Fabricate the legacy ISA bus (bus #31). + */ + mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; + Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); + + /* + * Locate the IOAPIC that manages the ISA IRQs (0-15). + */ + ioapic = mp_find_ioapic(0); + if (ioapic < 0) + return; + + intsrc.mpc_type = MP_INTSRC; + intsrc.mpc_irqflag = 0; /* Conforming */ + intsrc.mpc_srcbus = MP_ISA_BUS; + intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; + + /* + * Use the default configuration for the IRQs 0-15. These may be + * overriden by (MADT) interrupt source override entries. + */ + for (i = 0; i < 16; i++) { + + if (i == 2) continue; /* Don't connect IRQ2 */ + + intsrc.mpc_irqtype = i ? mp_INT : mp_ExtINT; /* 8259A to #0 */ + intsrc.mpc_srcbusirq = i; /* Identity mapped */ + intsrc.mpc_dstirq = i; + + Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, " + "%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, + (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, + intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, + intsrc.mpc_dstirq); + + mp_irqs[mp_irq_entries] = intsrc; + if (++mp_irq_entries == MAX_IRQ_SOURCES) + panic("Max # of irq sources exceeded!\n"); + } + + return; +} + +#endif /*CONFIG_X86_IO_APIC*/ + +#ifdef CONFIG_ACPI_PCI + +void __init mp_parse_prt (void) +{ + struct list_head *node = NULL; + struct acpi_prt_entry *entry = NULL; + int vector = 0; + int ioapic = -1; + int ioapic_pin = 0; + int irq = 0; + int idx, bit = 0; + + /* + * Parsing through the PCI Interrupt Routing Table (PRT) and program + * routing for all static (IOAPIC-direct) entries. + */ + list_for_each(node, &acpi_prt.entries) { + entry = list_entry(node, struct acpi_prt_entry, node); + + /* We're only interested in static (non-link) entries. */ + if (entry->link.handle) + continue; + + irq = entry->link.index; + ioapic = mp_find_ioapic(irq); + if (ioapic < 0) + continue; + ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start; + + /* + * Avoid pin reprogramming. PRTs typically include entries + * with redundant pin->irq mappings (but unique PCI devices); + * we only only program the IOAPIC on the first. + */ + bit = ioapic_pin % 32; + idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); + if (idx > 3) { + printk(KERN_ERR "Invalid reference to IOAPIC pin " + "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, + ioapic_pin); + continue; + } + if ((1<irq = irq; + continue; + } + + mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<irq = irq; + + printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> vector 0x%02x" + " -> IRQ %d\n", entry->id.segment, entry->id.bus, + entry->id.device, ('A' + entry->pin), + mp_ioapic_routing[ioapic].apic_id, ioapic_pin, vector, + entry->irq); + } + + return; +} + +#endif /*CONFIG_ACPI_PCI*/ + +#endif /*CONFIG_ACPI_BOOT*/ diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c --- a/arch/i386/kernel/setup.c Sun Jun 2 18:44:57 2002 +++ b/arch/i386/kernel/setup.c Sun Jun 2 18:44:57 2002 @@ -916,17 +916,11 @@ paging_init(); #ifdef CONFIG_ACPI_BOOT /* - * Initialize the ACPI boot-time table parser (gets the RSDP and SDT). - * Must do this after paging_init (due to reliance on fixmap, and thus - * the bootmem allocator) but before get_smp_config (to allow parsing - * of MADT). + * Parse the ACPI tables for possible boot-time SMP configuration. */ acpi_boot_init(*cmdline_p); #endif #ifdef CONFIG_X86_LOCAL_APIC - /* - * get boot-time SMP configuration: - */ if (smp_found_config) get_smp_config(); #endif diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c --- a/arch/i386/kernel/smpboot.c Sun Jun 2 18:44:57 2002 +++ b/arch/i386/kernel/smpboot.c Sun Jun 2 18:44:57 2002 @@ -174,7 +174,12 @@ if ((c->x86_model==7) && (c->x86_mask==0)) goto valid_k7; - /* Athlon 662, Duron 671, and Athlon >model 7 have capability bit */ + /* + * Athlon 662, Duron 671, and Athlon >model 7 have capability bit. + * It's worth noting that the A5 stepping (662) of some Athlon XP's + * have the MP bit set. + * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for more. + */ if (((c->x86_model==6) && (c->x86_mask>=2)) || ((c->x86_model==7) && (c->x86_mask>=1)) || (c->x86_model> 7)) @@ -632,7 +637,7 @@ } #endif -static int wakeup_secondary_via_NMI(int logical_apicid) +static int __init wakeup_secondary_via_NMI(int logical_apicid) /* * Poke the other CPU in the eye to wake it up. Remember that the normal * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this @@ -680,7 +685,7 @@ return (send_status | accept_status); } -static int wakeup_secondary_via_INIT(int phys_apicid, unsigned long start_eip) +static int __init wakeup_secondary_via_INIT(int phys_apicid, unsigned long start_eip) { unsigned long send_status = 0, accept_status = 0; int maxlvt, timeout, num_starts, j; diff -Nru a/arch/i386/lib/mmx.c b/arch/i386/lib/mmx.c --- a/arch/i386/lib/mmx.c Sun Jun 2 18:44:57 2002 +++ b/arch/i386/lib/mmx.c Sun Jun 2 18:44:57 2002 @@ -31,7 +31,7 @@ void *p; int i; - if (in_interrupt()) + if (unlikely(in_interrupt())) return __memcpy(to, from, len); p = to; @@ -57,7 +57,7 @@ : : "r" (from) ); - for(; i>0; i--) + for(; i>5; i--) { __asm__ __volatile__ ( "1: prefetch 320(%0)\n" @@ -372,7 +372,7 @@ void mmx_clear_page(void * page) { - if(in_interrupt()) + if(unlikely(in_interrupt())) slow_zero_page(page); else fast_clear_page(page); @@ -392,7 +392,7 @@ void mmx_copy_page(void *to, void *from) { - if(in_interrupt()) + if(unlikely(in_interrupt())) slow_copy_page(to, from); else fast_copy_page(to, from); diff -Nru a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c --- a/arch/i386/pci/acpi.c Sun Jun 2 18:44:58 2002 +++ b/arch/i386/pci/acpi.c Sun Jun 2 18:44:58 2002 @@ -2,73 +2,23 @@ #include #include "pci.h" -extern void eisa_set_level_irq(int irq); - -static int acpi_lookup_irq ( - struct pci_dev *dev, - int assign) +static int __init pci_acpi_init(void) { - int result = 0; - int irq = 0; - u8 pin; - - /* TBD: Select IRQ from possible to improve routing performance. */ - - /* Find IRQ pin */ - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - if (!pin) { - DBG(" -> no interrupt pin\n"); + if (pcibios_scanned) return 0; - } - pin = pin - 1; - - result = acpi_prt_get_irq(dev, pin, &irq); - if (!irq) - result = -ENODEV; - if (0 != result) { - printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s\n", - 'A'+pin, dev->slot_name); - return result; - } - - /* only check for the IRQ */ - if (!assign) { - printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", - irq, dev->slot_name); - return 1; - } - - dev->irq = irq; - /* also assign an IRQ */ - if (irq && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) { - result = acpi_prt_set_irq(dev, pin, irq); - if (0 != result) { - printk(KERN_WARNING "PCI: Could not assign IRQ %d to device %s\n", irq, dev->slot_name); - return result; - } - - eisa_set_level_irq(irq); - - printk(KERN_INFO "PCI: Assigned IRQ %d for device %s\n", irq, dev->slot_name); - } - - return 1; -} - -static int __init pci_acpi_init(void) -{ if (!(pci_probe & PCI_NO_ACPI_ROUTING)) { - if (acpi_prts.count) { + if (!acpi_pci_irq_init()) { printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); printk(KERN_INFO "PCI: if you experience problems, try using option 'pci=noacpi'\n"); - pci_use_acpi_routing = 1; - pci_lookup_irq = acpi_lookup_irq; + pcibios_scanned++; + pcibios_enable_irq = acpi_pci_irq_enable; } else printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n"); } + return 0; } -arch_initcall(pci_acpi_init); +subsys_initcall(pci_acpi_init); diff -Nru a/arch/i386/pci/common.c b/arch/i386/pci/common.c --- a/arch/i386/pci/common.c Sun Jun 2 18:44:57 2002 +++ b/arch/i386/pci/common.c Sun Jun 2 18:44:57 2002 @@ -28,6 +28,12 @@ int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL; /* + * legacy, numa, and acpi all want to call pcibios_scan_root + * from their initcalls. This flag prevents that. + */ +int pcibios_scanned; + +/* * This interrupt-safe spinlock protects all accesses to PCI * configuration space. */ @@ -201,6 +207,6 @@ if ((err = pcibios_enable_resources(dev)) < 0) return err; - pcibios_enable_irq(dev); - return 0; + + return pcibios_enable_irq(dev); } diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c --- a/arch/i386/pci/irq.c Sun Jun 2 18:44:58 2002 +++ b/arch/i386/pci/irq.c Sun Jun 2 18:44:58 2002 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -22,7 +21,6 @@ #define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24)) #define PIRQ_VERSION 0x0100 -int pci_use_acpi_routing = 0; int broken_hp_bios_irq9; static struct irq_routing_table *pirq_table; @@ -46,7 +44,7 @@ int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new); }; -int (*pci_lookup_irq)(struct pci_dev * dev, int assign) = NULL; +int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; /* * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table. @@ -690,7 +688,7 @@ { DBG("PCI: IRQ init\n"); - if (pci_lookup_irq) + if (pcibios_enable_irq) return 0; pirq_table = pirq_find_routing_table(); @@ -712,7 +710,9 @@ if (io_apic_assign_pci_irqs) pirq_table = NULL; } - pci_lookup_irq = pcibios_lookup_irq; + + pcibios_enable_irq = pirq_enable_irq; + pcibios_fixup_irqs(); return 0; } @@ -781,7 +781,7 @@ * Still no IRQ? Try to lookup one... */ if (pin && !dev->irq) - pci_lookup_irq(dev, 0); + pcibios_lookup_irq(dev, 0); } } @@ -794,11 +794,11 @@ pirq_penalty[irq] += 100; } -void pcibios_enable_irq(struct pci_dev *dev) +int pirq_enable_irq(struct pci_dev *dev) { u8 pin; pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - if (pin && !pci_lookup_irq(dev, 1) && !dev->irq) { + if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { char *msg; if (io_apic_assign_pci_irqs) msg = " Probably buggy MP table."; @@ -809,4 +809,6 @@ printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", 'A' + pin - 1, dev->slot_name, msg); } + + return 0; } diff -Nru a/arch/i386/pci/legacy.c b/arch/i386/pci/legacy.c --- a/arch/i386/pci/legacy.c Sun Jun 2 18:44:57 2002 +++ b/arch/i386/pci/legacy.c Sun Jun 2 18:44:57 2002 @@ -42,11 +42,14 @@ return 0; } + if (pcibios_scanned++) + return 0; + printk("PCI: Probing PCI hardware\n"); pci_root_bus = pcibios_scan_root(0); - if (!pci_use_acpi_routing) - pcibios_fixup_peer_bridges(); + pcibios_fixup_peer_bridges(); + return 0; } diff -Nru a/arch/i386/pci/numa.c b/arch/i386/pci/numa.c --- a/arch/i386/pci/numa.c Sun Jun 2 18:44:56 2002 +++ b/arch/i386/pci/numa.c Sun Jun 2 18:44:56 2002 @@ -104,6 +104,9 @@ pci_config_read = pci_conf1_read; pci_config_write = pci_conf1_write; + if (pcibios_scanned++) + return 0; + pci_root_bus = pcibios_scan_root(0); if (clustered_apic_mode && (numnodes > 1)) { for (quad = 1; quad < numnodes; ++quad) { diff -Nru a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h --- a/arch/i386/pci/pci.h Sun Jun 2 18:44:58 2002 +++ b/arch/i386/pci/pci.h Sun Jun 2 18:44:58 2002 @@ -66,10 +66,10 @@ extern unsigned int pcibios_irq_mask; -extern int pci_use_acpi_routing; +extern int pcibios_scanned; extern spinlock_t pci_config_lock; void pcibios_fixup_irqs(void); -void pcibios_enable_irq(struct pci_dev *dev); +int pirq_enable_irq(struct pci_dev *dev); -extern int (*pci_lookup_irq)(struct pci_dev * dev, int assign); +extern int (*pcibios_enable_irq)(struct pci_dev *dev); diff -Nru a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c --- a/arch/m68k/atari/stram.c Sun Jun 2 18:44:56 2002 +++ b/arch/m68k/atari/stram.c Sun Jun 2 18:44:56 2002 @@ -315,7 +315,7 @@ otherwise just use the end of kernel data (= start_mem) */ swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE : start_mem; /* decrement by one page, rest of kernel assumes that first swap page - * is always reserved and maybe doesn't handle SWP_ENTRY == 0 + * is always reserved and maybe doesn't handle swp_entry == 0 * correctly */ swap_start -= PAGE_SIZE; swap_end = stram_end; @@ -749,7 +749,7 @@ } if (map[i]) { - entry = SWP_ENTRY(stram_swap_type, i); + entry = swp_entry(stram_swap_type, i); DPRINTK("unswap: map[i=%lu]=%u nr_swap=%u\n", i, map[i], nr_swap_pages); diff -Nru a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c --- a/arch/ppc/kernel/syscalls.c Sun Jun 2 18:44:57 2002 +++ b/arch/ppc/kernel/syscalls.c Sun Jun 2 18:44:57 2002 @@ -117,7 +117,7 @@ if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp))) || (ret = copy_from_user(&tmp, (struct ipc_kludge *) ptr, - sizeof (tmp)))) + sizeof (tmp)) ? -EFAULT : 0) break; ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); diff -Nru a/arch/ppc64/Makefile b/arch/ppc64/Makefile --- a/arch/ppc64/Makefile Sun Jun 2 18:44:56 2002 +++ b/arch/ppc64/Makefile Sun Jun 2 18:44:56 2002 @@ -18,7 +18,8 @@ LINKFLAGS = -T arch/ppc64/vmlinux.lds -Bstatic \ -e $(KERNELLOAD) -Ttext $(KERNELLOAD) CFLAGS := $(CFLAGS) -fsigned-char -msoft-float -pipe \ - -Wno-uninitialized -mminimal-toc -mtraceback=full + -Wno-uninitialized -mminimal-toc -mtraceback=full \ + -Wa,-mpower4 -finline-limit-2000 CPP = $(CC) -E $(CFLAGS) diff -Nru a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c --- a/arch/ppc64/boot/main.c Sun Jun 2 18:44:57 2002 +++ b/arch/ppc64/boot/main.c Sun Jun 2 18:44:57 2002 @@ -153,7 +153,7 @@ rec = bi_rec_alloc(rec, 2); rec->tag = BI_MACHTYPE; - rec->data[0] = _MACH_pSeries; + rec->data[0] = PLATFORM_PSERIES; rec->data[1] = 1; if ( initrd_size > 0 ) { diff -Nru a/arch/ppc64/config.in b/arch/ppc64/config.in --- a/arch/ppc64/config.in Sun Jun 2 18:44:56 2002 +++ b/arch/ppc64/config.in Sun Jun 2 18:44:56 2002 @@ -5,7 +5,6 @@ define_bool CONFIG_UID16 n define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y -define_bool CONFIG_GENERIC_BUST_SPINLOCK n define_bool CONFIG_GENERIC_ISA_DMA y define_bool CONFIG_HAVE_DEC_LOCK y @@ -30,8 +29,6 @@ if [ "$CONFIG_PPC_ISERIES" = "y" ]; then define_bool CONFIG_MSCHUNKS y -else -bool 'MsChunks Physical to Absolute address translation support' CONFIG_MSCHUNKS fi endmenu @@ -70,6 +67,11 @@ if [ "$CONFIG_PPC_ISERIES" != "y" ]; then bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE + + bool 'Default bootloader kernel arguments' CONFIG_CMDLINE_BOOL + if [ "$CONFIG_CMDLINE_BOOL" = "y" ] ; then + string 'Initial kernel command string' CONFIG_CMDLINE "console=ttyS0,9600 console=tty0 root=/dev/sda2" + fi fi endmenu @@ -103,8 +105,12 @@ fi endmenu +source drivers/message/fusion/Config.in + source drivers/ieee1394/Config.in +source drivers/message/i2o/Config.in + if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment comment 'Network device support' @@ -181,6 +187,9 @@ fi source drivers/char/Config.in + +source drivers/media/Config.in + source fs/Config.in mainmenu_option next_comment @@ -194,13 +203,21 @@ source drivers/usb/Config.in +source net/bluetooth/Config.in + mainmenu_option next_comment comment 'Kernel hacking' -bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ -bool 'Include kgdb kernel debugger' CONFIG_KGDB -bool 'Include xmon kernel debugger' CONFIG_XMON -bool 'Include PPCDBG realtime debugging' CONFIG_PPCDBG +bool 'Kernel debugging' CONFIG_DEBUG_KERNEL +if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then + bool ' Debug memory allocations' CONFIG_DEBUG_SLAB + bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ + bool ' Include xmon kernel debugger' CONFIG_XMON + if [ "$CONFIG_XMON" = "y" ]; then + bool ' Enable xmon by default' CONFIG_XMON_DEFAULT + fi + bool ' Include PPCDBG realtime debugging' CONFIG_PPCDBG +fi endmenu source lib/Config.in diff -Nru a/arch/ppc64/defconfig b/arch/ppc64/defconfig --- a/arch/ppc64/defconfig Sun Jun 2 18:44:57 2002 +++ b/arch/ppc64/defconfig Sun Jun 2 18:44:57 2002 @@ -4,7 +4,6 @@ # CONFIG_UID16 is not set # CONFIG_RWSEM_GENERIC_SPINLOCK is not set CONFIG_RWSEM_XCHGADD_ALGORITHM=y -# CONFIG_GENERIC_BUST_SPINLOCK is not set CONFIG_GENERIC_ISA_DMA=y CONFIG_HAVE_DEC_LOCK=y @@ -38,9 +37,7 @@ CONFIG_SMP=y CONFIG_IRQ_ALL_CPUS=y # CONFIG_HMT is not set -# CONFIG_PPC_EEH is not set # CONFIG_PREEMPT is not set -# CONFIG_MSCHUNKS is not set # # General setup @@ -133,6 +130,11 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set @@ -153,7 +155,6 @@ # ATA/IDE/MFM/RLL support # # CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set # CONFIG_BLK_DEV_HD is not set # @@ -177,6 +178,7 @@ # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # # CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set @@ -233,11 +235,26 @@ # CONFIG_SCSI_MAC53C94 is not set # +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# # IEEE 1394 (FireWire) support (EXPERIMENTAL) # # CONFIG_IEEE1394 is not set # +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# # Network device support # CONFIG_NETDEVICES=y @@ -282,12 +299,9 @@ # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set -# CONFIG_DE2104X is not set -# CONFIG_TULIP is not set -# CONFIG_DE4X5 is not set # CONFIG_DGRS is not set -# CONFIG_DM9102 is not set CONFIG_EEPRO100=y +# CONFIG_E100 is not set # CONFIG_LNE390 is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set @@ -306,20 +320,21 @@ # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_VIA_RHINE_MMIO is not set -# CONFIG_WINBOND_840 is not set # CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # CONFIG_ACENIC=y -# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set +# CONFIG_E1000 is not set # CONFIG_MYRI_SBUS is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PLIP is not set @@ -337,6 +352,7 @@ CONFIG_TR=y CONFIG_IBMOL=y # CONFIG_IBMLS is not set +# CONFIG_3C359 is not set # CONFIG_TMS380TR is not set # CONFIG_NET_FC is not set # CONFIG_RCPCI is not set @@ -348,6 +364,11 @@ # CONFIG_WAN is not set # +# "Tulip" family network device support +# +# CONFIG_NET_TULIP is not set + +# # Amateur Radio support # # CONFIG_HAMRADIO is not set @@ -360,7 +381,7 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set # # Old CD-ROM drivers (not SCSI, not IDE) @@ -414,6 +435,25 @@ # CONFIG_FONT_SUN8x16 is not set # CONFIG_FONT_PEARL_8x8 is not set # CONFIG_FONT_ACORN_8x8 is not set + +# +# Input device support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_GAMEPORT_NS558 is not set +# CONFIG_GAMEPORT_L4 is not set +# CONFIG_INPUT_EMU10K1 is not set +# CONFIG_GAMEPORT_PCIGAME is not set +# CONFIG_GAMEPORT_FM801 is not set +# CONFIG_GAMEPORT_CS461x is not set +# CONFIG_SERIO is not set +# CONFIG_SERIO_SERPORT is not set CONFIG_VIOPATH=y # @@ -461,6 +501,11 @@ # CONFIG_DRM is not set # +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# # File systems # # CONFIG_QUOTA is not set @@ -490,6 +535,9 @@ CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set +CONFIG_JFS_FS=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set # CONFIG_MINIX_FS is not set # CONFIG_VXFS_FS is not set # CONFIG_NTFS_FS is not set @@ -520,9 +568,11 @@ # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y +# CONFIG_NFSD_TCP is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y CONFIG_SMB_FS=y # CONFIG_SMB_NLS_DEFAULT is not set # CONFIG_NCP_FS is not set @@ -569,6 +619,7 @@ # CONFIG_NLS_CODEPAGE_949 is not set # CONFIG_NLS_CODEPAGE_874 is not set # CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set @@ -596,119 +647,18 @@ # CONFIG_USB is not set # -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_OHCI_HCD is not set -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# -# CONFIG_USB_HID is not set -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_WACOM is not set - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_PWC is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_STV680 is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_KONICAWC is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SERIAL_OMNINET is not set - -# -# USB Miscellaneous drivers +# Bluetooth support # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_AUERSWALD is not set +# CONFIG_BLUEZ is not set # # Kernel hacking # +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y -# CONFIG_KGDB is not set CONFIG_XMON=y +CONFIG_XMON_DEFAULT=y # CONFIG_PPCDBG is not set # diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile Sun Jun 2 18:44:57 2002 +++ b/arch/ppc64/kernel/Makefile Sun Jun 2 18:44:57 2002 @@ -32,8 +32,6 @@ obj-y += rtasd.o nvram.o endif -obj-$(CONFIG_KGDB) += ppc-stub.o - obj-$(CONFIG_SMP) += smp.o obj-y += prom.o lmb.o rtas.o rtas-proc.o chrp_setup.o i8259.o diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S --- a/arch/ppc64/kernel/entry.S Sun Jun 2 18:44:56 2002 +++ b/arch/ppc64/kernel/entry.S Sun Jun 2 18:44:56 2002 @@ -56,7 +56,6 @@ * Handle a system call. */ _GLOBAL(DoSyscall) - std r0,THREAD+LAST_SYSCALL(r13) ld r11,_CCR(r1) /* Clear SO bit in CR */ lis r10,0x1000 andc r11,r11,r10 diff -Nru a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c --- a/arch/ppc64/kernel/idle.c Sun Jun 2 18:44:58 2002 +++ b/arch/ppc64/kernel/idle.c Sun Jun 2 18:44:58 2002 @@ -84,6 +84,8 @@ lpaca = get_paca(); while (1) { + irq_stat[smp_processor_id()].idle_timestamp = jiffies; + if (lpaca->xLpPaca.xSharedProc) { if (ItLpQueue_isLpIntPending(lpaca->lpQueuePtr)) process_iSeries_events(); @@ -123,6 +125,7 @@ long oldval; while (1) { + irq_stat[smp_processor_id()].idle_timestamp = jiffies; oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); if (!oldval) { @@ -146,3 +149,8 @@ } #endif /* CONFIG_PPC_ISERIES */ + +void default_idle(void) +{ + barrier(); +} diff -Nru a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c --- a/arch/ppc64/kernel/ioctl32.c Sun Jun 2 18:44:58 2002 +++ b/arch/ppc64/kernel/ioctl32.c Sun Jun 2 18:44:58 2002 @@ -3756,6 +3756,7 @@ COMPATIBLE_IOCTL(TCSETSF), COMPATIBLE_IOCTL(TIOCLINUX), COMPATIBLE_IOCTL(TIOCSTART), +COMPATIBLE_IOCTL(TIOCSTOP), /* Little t */ COMPATIBLE_IOCTL(TIOCGETD), COMPATIBLE_IOCTL(TIOCSETD), @@ -4336,8 +4337,6 @@ COMPATIBLE_IOCTL(HCIDEVUP), COMPATIBLE_IOCTL(HCIDEVDOWN), COMPATIBLE_IOCTL(HCIDEVRESET), -COMPATIBLE_IOCTL(HCIRESETSTAT), -COMPATIBLE_IOCTL(HCIGETINFO), COMPATIBLE_IOCTL(HCIGETDEVLIST), COMPATIBLE_IOCTL(HCISETRAW), COMPATIBLE_IOCTL(HCISETSCAN), diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c --- a/arch/ppc64/kernel/irq.c Sun Jun 2 18:44:57 2002 +++ b/arch/ppc64/kernel/irq.c Sun Jun 2 18:44:57 2002 @@ -75,22 +75,6 @@ int ppc_spurious_interrupts = 0; struct irqaction *ppc_irq_action[NR_IRQS]; unsigned long lpEvent_count = 0; -#ifdef CONFIG_XMON -extern void xmon(struct pt_regs *regs); -extern int xmon_bpt(struct pt_regs *regs); -extern int xmon_sstep(struct pt_regs *regs); -extern int xmon_iabr_match(struct pt_regs *regs); -extern int xmon_dabr_match(struct pt_regs *regs); -extern void (*xmon_fault_handler)(struct pt_regs *regs); -#endif -#ifdef CONFIG_XMON -extern void (*debugger)(struct pt_regs *regs); -extern int (*debugger_bpt)(struct pt_regs *regs); -extern int (*debugger_sstep)(struct pt_regs *regs); -extern int (*debugger_iabr_match)(struct pt_regs *regs); -extern int (*debugger_dabr_match)(struct pt_regs *regs); -extern void (*debugger_fault_handler)(struct pt_regs *regs); -#endif /* nasty hack for shared irq's since we need to do kmalloc calls but * can't very early in the boot when we need to do a request irq. @@ -410,6 +394,75 @@ __cli(); } +#ifdef CONFIG_SMP +extern unsigned int irq_affinity [NR_IRQS]; + +typedef struct { + unsigned long cpu; + unsigned long timestamp; +} ____cacheline_aligned irq_balance_t; + +static irq_balance_t irq_balance[NR_IRQS] __cacheline_aligned + = { [ 0 ... NR_IRQS-1 ] = { 1, 0 } }; + +#define IDLE_ENOUGH(cpu,now) \ + (idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > ((HZ/100)+1))) + +#define IRQ_ALLOWED(cpu,allowed_mask) \ + ((1 << cpu) & (allowed_mask)) + +static unsigned long move(unsigned long curr_cpu, unsigned long allowed_mask, + unsigned long now, int direction) +{ + int search_idle = 1; + int cpu = curr_cpu; + + goto inside; + + do { + if (unlikely(cpu == curr_cpu)) + search_idle = 0; +inside: + if (direction == 1) { + cpu++; + if (cpu >= smp_num_cpus) + cpu = 0; + } else { + cpu--; + if (cpu == -1) + cpu = smp_num_cpus-1; + } + } while (!IRQ_ALLOWED(cpu,allowed_mask) || + (search_idle && !IDLE_ENOUGH(cpu,now))); + + return cpu; +} + +static inline void balance_irq(int irq) +{ + irq_balance_t *entry = irq_balance + irq; + unsigned long now = jiffies; + + if (unlikely(entry->timestamp != now)) { + unsigned long allowed_mask; + unsigned long random_number; + + if (!irq_desc[irq].handler->set_affinity) + return; + + random_number = mftb(); + random_number &= 1; + + allowed_mask = cpu_online_map & irq_affinity[irq]; + entry->timestamp = now; + entry->cpu = move(entry->cpu, allowed_mask, now, random_number); + irq_desc[irq].handler->set_affinity(irq, 1 << entry->cpu); + } +} +#else +#define balance_irq(irq) do { } while (0) +#endif + /* * Eventually, this should take an array of interrupts and an array size * so it can dispatch multiple interrupts. @@ -420,6 +473,8 @@ struct irqaction *action; int cpu = smp_processor_id(); irq_desc_t *desc = irq_desc + irq; + + balance_irq(irq); kstat.irqs[cpu][irq]++; spin_lock(&desc->lock); diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Sun Jun 2 18:44:57 2002 +++ b/arch/ppc64/kernel/misc.S Sun Jun 2 18:44:57 2002 @@ -266,24 +266,6 @@ blr /* - * Copy a whole page. Assumes a 4096B page size. - */ -_GLOBAL(copy_page) - clrrdi r3,r3,12 /* Page align */ - clrrdi r4,r4,12 /* Page align */ - li r5,256 - mtctr r5 - addi r3,r3,-8 - addi r4,r4,-8 - -1: ld r6,8(r4) - ldu r7,16(r4) - std r6,8(r3) - stdu r7,16(r3) - bdnz+ 1b - blr - -/* * I/O string operations * * insb(port, buf, len) @@ -649,7 +631,7 @@ .llong .sys32_init_module .llong .sys32_delete_module .llong .sys32_get_kernel_syms /* 130 */ - .llong .sys32_quotactl + .llong .sys_quotactl .llong .sys32_getpgid .llong .sys_fchdir .llong .sys32_bdflush @@ -740,7 +722,11 @@ .llong .sys_lremovexattr .llong .sys_fremovexattr /* 220 */ .llong .sys_futex - .rept NR_syscalls-221 + .llong .sys_ni_syscall /* reserved for tux */ + .llong .sys32_sched_setaffinity + .llong .sys32_sched_getaffinity + + .rept NR_syscalls-224 .llong .sys_ni_syscall .endr #endif @@ -969,6 +955,10 @@ .llong .sys_lremovexattr .llong .sys_fremovexattr /* 220 */ .llong .sys_futex - .rept NR_syscalls-221 + .llong .sys_ni_syscall /* reserved for tux */ + .llong .sys_sched_setaffinity + .llong .sys_sched_getaffinity + + .rept NR_syscalls-224 .llong .sys_ni_syscall .endr diff -Nru a/arch/ppc64/kernel/mk_defs.c b/arch/ppc64/kernel/mk_defs.c --- a/arch/ppc64/kernel/mk_defs.c Sun Jun 2 18:44:56 2002 +++ b/arch/ppc64/kernel/mk_defs.c Sun Jun 2 18:44:56 2002 @@ -52,7 +52,6 @@ /* task_struct->thread */ DEFINE(THREAD, offsetof(struct task_struct, thread)); - DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall)); DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr)); diff -Nru a/arch/ppc64/kernel/pSeries_htab.c b/arch/ppc64/kernel/pSeries_htab.c --- a/arch/ppc64/kernel/pSeries_htab.c Sun Jun 2 18:44:57 2002 +++ b/arch/ppc64/kernel/pSeries_htab.c Sun Jun 2 18:44:57 2002 @@ -359,7 +359,7 @@ /* Invalidate the tlb */ if (!large && local && __is_processor(PV_POWER4)) { - _tlbiel(va, large); + _tlbiel(va); } else { spin_lock_irqsave(&pSeries_tlbie_lock, flags); _tlbie(va, large); diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c --- a/arch/ppc64/kernel/pci.c Sun Jun 2 18:44:57 2002 +++ b/arch/ppc64/kernel/pci.c Sun Jun 2 18:44:57 2002 @@ -498,6 +498,8 @@ } +subsys_initcall(pcibios_init); + int __init pcibios_assign_all_busses(void) { diff -Nru a/arch/ppc64/kernel/ppc-stub.c b/arch/ppc64/kernel/ppc-stub.c --- a/arch/ppc64/kernel/ppc-stub.c Sun Jun 2 18:44:57 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,739 +0,0 @@ -/* - * ppc-stub.c: KGDB support for the Linux kernel. - * - * adapted from arch/sparc/kernel/sparc-stub.c for the PowerPC - * some stuff borrowed from Paul Mackerras' xmon - * Copyright (C) 1998 Michael AK Tesch (tesch@cs.wisc.edu) - * - * Modifications to run under Linux - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * - * This file originally came from the gdb sources, and the - * copyright notices have been retained below. - */ - -/**************************************************************************** - - THIS SOFTWARE IS NOT COPYRIGHTED - - HP offers the following for use in the public domain. HP makes no - warranty with regard to the software or its performance and the - user accepts the software "AS IS" with all faults. - - HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD - TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - -****************************************************************************/ - -/**************************************************************************** - * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ - * - * Module name: remcom.c $ - * Revision: 1.34 $ - * Date: 91/03/09 12:29:49 $ - * Contributor: Lake Stevens Instrument Division$ - * - * Description: low level support for gdb debugger. $ - * - * Considerations: only works on target hardware $ - * - * Written by: Glenn Engel $ - * ModuleState: Experimental $ - * - * NOTES: See Below $ - * - * Modified for SPARC by Stu Grossman, Cygnus Support. - * - * This code has been extensively tested on the Fujitsu SPARClite demo board. - * - * To enable debugger support, two things need to happen. One, a - * call to set_debug_traps() is necessary in order to allow any breakpoints - * or error conditions to be properly intercepted and reported to gdb. - * Two, a breakpoint needs to be generated to begin communication. This - * is most easily accomplished by a call to breakpoint(). Breakpoint() - * simulates a breakpoint by executing a trap #1. - * - ************* - * - * The following gdb commands are supported: - * - * command function Return value - * - * g return the value of the CPU registers hex data or ENN - * G set the value of the CPU registers OK or ENN - * qOffsets Get section offsets. Reply is Text=xxx;Data=yyy;Bss=zzz - * - * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN - * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN - * - * c Resume at current address SNN ( signal NN) - * cAA..AA Continue at address AA..AA SNN - * - * s Step one instruction SNN - * sAA..AA Step one instruction from AA..AA SNN - * - * k kill - * - * ? What was the last sigval ? SNN (signal NN) - * - * bBB..BB Set baud rate to BB..BB OK or BNN, then sets - * baud rate - * - * All commands and responses are sent with a packet which includes a - * checksum. A packet consists of - * - * $#. - * - * where - * :: - * :: > - * - * When a packet is received, it is first acknowledged with either '+' or '-'. - * '+' indicates a successful transfer. '-' indicates a failed transfer. - * - * Example: - * - * Host: Reply: - * $m0,10#2a +$00010203040506070809101112131415#42 - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -void breakinst(void); - -/* - * BUFMAX defines the maximum number of characters in inbound/outbound buffers - * at least NUMREGBYTES*2 are needed for register packets - */ -#define BUFMAX 2048 -static char remcomInBuffer[BUFMAX]; -static char remcomOutBuffer[BUFMAX]; - -static int initialized = 0; -static int kgdb_active = 0; -static int kgdb_started = 0; -static u_int fault_jmp_buf[100]; -static int kdebug; - -static const char hexchars[]="0123456789abcdef"; - -/* Place where we save old trap entries for restoration - sparc*/ -/* struct tt_entry kgdb_savettable[256]; */ -/* typedef void (*trapfunc_t)(void); */ - -#if 0 -/* Install an exception handler for kgdb */ -static void exceptionHandler(int tnum, unsigned int *tfunc) -{ - /* We are dorking with a live trap table, all irqs off */ -} -#endif - -int -kgdb_setjmp(long *buf) -{ - asm ("mflr 0; stw 0,0(%0);" - "stw 1,4(%0); stw 2,8(%0);" - "mfcr 0; stw 0,12(%0);" - "stmw 13,16(%0)" - : : "r" (buf)); - /* XXX should save fp regs as well */ - return 0; -} -void -kgdb_longjmp(long *buf, int val) -{ - if (val == 0) - val = 1; - asm ("lmw 13,16(%0);" - "lwz 0,12(%0); mtcrf 0x38,0;" - "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);" - "mtlr 0; mr 3,%1" - : : "r" (buf), "r" (val)); -} -/* Convert ch from a hex digit to an int */ -static int -hex(unsigned char ch) -{ - if (ch >= 'a' && ch <= 'f') - return ch-'a'+10; - if (ch >= '0' && ch <= '9') - return ch-'0'; - if (ch >= 'A' && ch <= 'F') - return ch-'A'+10; - return -1; -} - -/* Convert the memory pointed to by mem into hex, placing result in buf. - * Return a pointer to the last char put in buf (null), in case of mem fault, - * return 0. - */ -static unsigned char * -mem2hex(char *mem, char *buf, int count) -{ - unsigned char ch; - - if (kgdb_setjmp((long*)fault_jmp_buf) == 0) { - debugger_fault_handler = kgdb_fault_handler; - while (count-- > 0) { - ch = *mem++; - *buf++ = hexchars[ch >> 4]; - *buf++ = hexchars[ch & 0xf]; - } - } else { - /* error condition */ - } - debugger_fault_handler = 0; - *buf = 0; - return buf; -} - -/* convert the hex array pointed to by buf into binary to be placed in mem - * return a pointer to the character AFTER the last byte written. -*/ -static char * -hex2mem(char *buf, char *mem, int count) -{ - int i; - unsigned char ch; - - if (kgdb_setjmp((long*)fault_jmp_buf) == 0) { - debugger_fault_handler = kgdb_fault_handler; - for (i=0; i# */ -static void -getpacket(char *buffer) -{ - unsigned char checksum; - unsigned char xmitcsum; - int i; - int count; - unsigned char ch; - - do { - /* wait around for the start character, ignore all other - * characters */ - while ((ch = (getDebugChar() & 0x7f)) != '$') ; - - checksum = 0; - xmitcsum = -1; - - count = 0; - - /* now, read until a # or end of buffer is found */ - while (count < BUFMAX) { - ch = getDebugChar() & 0x7f; - if (ch == '#') - break; - checksum = checksum + ch; - buffer[count] = ch; - count = count + 1; - } - - if (count >= BUFMAX) - continue; - - buffer[count] = 0; - - if (ch == '#') { - xmitcsum = hex(getDebugChar() & 0x7f) << 4; - xmitcsum |= hex(getDebugChar() & 0x7f); - if (checksum != xmitcsum) - putDebugChar('-'); /* failed checksum */ - else { - putDebugChar('+'); /* successful transfer */ - /* if a sequence char is present, reply the ID */ - if (buffer[2] == ':') { - putDebugChar(buffer[0]); - putDebugChar(buffer[1]); - /* remove sequence chars from buffer */ - count = strlen(buffer); - for (i=3; i <= count; i++) - buffer[i-3] = buffer[i]; - } - } - } - } while (checksum != xmitcsum); -} - -/* send the packet in buffer. */ -static void putpacket(unsigned char *buffer) -{ - unsigned char checksum; - int count; - unsigned char ch, recv; - - /* $#. */ - do { - putDebugChar('$'); - checksum = 0; - count = 0; - - while ((ch = buffer[count])) { - putDebugChar(ch); - checksum += ch; - count += 1; - } - - putDebugChar('#'); - putDebugChar(hexchars[checksum >> 4]); - putDebugChar(hexchars[checksum & 0xf]); - recv = getDebugChar(); - } while ((recv & 0x7f) != '+'); -} - -static void kgdb_flush_cache_all(void) -{ - flush_instruction_cache(); -} - - -/* Set up exception handlers for tracing and breakpoints - * [could be called kgdb_init()] - */ -void set_debug_traps(void) -{ -#if 0 - unsigned char c; - - save_and_cli(flags); - - /* In case GDB is started before us, ack any packets (presumably - * "$?#xx") sitting there. - * - * I've found this code causes more problems than it solves, - * so that's why it's commented out. GDB seems to work fine - * now starting either before or after the kernel -bwb - */ - - while((c = getDebugChar()) != '$'); - while((c = getDebugChar()) != '#'); - c = getDebugChar(); /* eat first csum byte */ - c = getDebugChar(); /* eat second csum byte */ - putDebugChar('+'); /* ack it */ -#endif - debugger = kgdb; - debugger_bpt = kgdb_bpt; - debugger_sstep = kgdb_sstep; - debugger_iabr_match = kgdb_iabr_match; - debugger_dabr_match = kgdb_dabr_match; - - initialized = 1; -} - -static void kgdb_fault_handler(struct pt_regs *regs) -{ - kgdb_longjmp((long*)fault_jmp_buf, 1); -} - -int kgdb_bpt(struct pt_regs *regs) -{ - handle_exception(regs); - return 1; -} - -int kgdb_sstep(struct pt_regs *regs) -{ - handle_exception(regs); - return 1; -} - -void kgdb(struct pt_regs *regs) -{ - handle_exception(regs); -} - -int kgdb_iabr_match(struct pt_regs *regs) -{ - printk("kgdb doesn't support iabr, what?!?\n"); - handle_exception(regs); - return 1; -} - -int kgdb_dabr_match(struct pt_regs *regs) -{ - printk("kgdb doesn't support dabr, what?!?\n"); - handle_exception(regs); - return 1; -} - -/* Convert the SPARC hardware trap type code to a unix signal number. */ -/* - * This table contains the mapping between PowerPC hardware trap types, and - * signals, which are primarily what GDB understands. - */ -static struct hard_trap_info -{ - unsigned int tt; /* Trap type code for powerpc */ - unsigned char signo; /* Signal that we map this trap into */ -} hard_trap_info[] = { - { 0x200, SIGSEGV }, /* machine check */ - { 0x300, SIGSEGV }, /* address error (store) */ - { 0x400, SIGBUS }, /* instruction bus error */ - { 0x500, SIGINT }, /* interrupt */ - { 0x600, SIGBUS }, /* alingment */ - { 0x700, SIGTRAP }, /* breakpoint trap */ - { 0x800, SIGFPE }, /* fpu unavail */ - { 0x900, SIGALRM }, /* decrementer */ - { 0xa00, SIGILL }, /* reserved */ - { 0xb00, SIGILL }, /* reserved */ - { 0xc00, SIGCHLD }, /* syscall */ - { 0xd00, SIGTRAP }, /* single-step/watch */ - { 0xe00, SIGFPE }, /* fp assist */ - { 0, 0} /* Must be last */ -}; - -static int computeSignal(unsigned int tt) -{ - struct hard_trap_info *ht; - - for (ht = hard_trap_info; ht->tt && ht->signo; ht++) - if (ht->tt == tt) - return ht->signo; - - return SIGHUP; /* default for things we don't know about */ -} - -#define PC_REGNUM 64 -#define SP_REGNUM 1 - -/* - * This function does all command processing for interfacing to gdb. - */ -static void -handle_exception (struct pt_regs *regs) -{ - int sigval; - int addr; - int length; - char *ptr; - unsigned long msr; - - if (debugger_fault_handler) { - debugger_fault_handler(regs); - panic("kgdb longjump failed!\n"); - } - if (kgdb_active) { - printk("interrupt while in kgdb, returning\n"); - return; - } - kgdb_active = 1; - kgdb_started = 1; - -#ifdef KGDB_DEBUG - printk("kgdb: entering handle_exception; trap [0x%x]\n", - (unsigned int)regs->trap); -#endif - - kgdb_interruptible(0); - lock_kernel(); - msr = get_msr(); - set_msr(msr & ~MSR_EE); /* disable interrupts */ - - if (regs->nip == (unsigned long)breakinst) { - /* Skip over breakpoint trap insn */ - regs->nip += 4; - } - - /* reply to host that an exception has occurred */ - sigval = computeSignal(regs->trap); - ptr = remcomOutBuffer; - -#if 0 - *ptr++ = 'S'; - *ptr++ = hexchars[sigval >> 4]; - *ptr++ = hexchars[sigval & 0xf]; -#else - *ptr++ = 'T'; - *ptr++ = hexchars[sigval >> 4]; - *ptr++ = hexchars[sigval & 0xf]; - *ptr++ = hexchars[PC_REGNUM >> 4]; - *ptr++ = hexchars[PC_REGNUM & 0xf]; - *ptr++ = ':'; - ptr = mem2hex((char *)®s->nip, ptr, 4); - *ptr++ = ';'; - *ptr++ = hexchars[SP_REGNUM >> 4]; - *ptr++ = hexchars[SP_REGNUM & 0xf]; - *ptr++ = ':'; - ptr = mem2hex(((char *)®s) + SP_REGNUM*4, ptr, 4); - *ptr++ = ';'; -#endif - - *ptr++ = 0; - - putpacket(remcomOutBuffer); - - /* XXX We may want to add some features dealing with poking the - * XXX page tables, ... (look at sparc-stub.c for more info) - * XXX also required hacking to the gdb sources directly... - */ - - while (1) { - remcomOutBuffer[0] = 0; - - getpacket(remcomInBuffer); - switch (remcomInBuffer[0]) { - case '?': /* report most recent signal */ - remcomOutBuffer[0] = 'S'; - remcomOutBuffer[1] = hexchars[sigval >> 4]; - remcomOutBuffer[2] = hexchars[sigval & 0xf]; - remcomOutBuffer[3] = 0; - break; -#if 0 - case 'q': /* this screws up gdb for some reason...*/ - { - extern long _start, sdata, __bss_start; - - ptr = &remcomInBuffer[1]; - if (strncmp(ptr, "Offsets", 7) != 0) - break; - - ptr = remcomOutBuffer; - sprintf(ptr, "Text=%8.8x;Data=%8.8x;Bss=%8.8x", - &_start, &sdata, &__bss_start); - break; - } -#endif - case 'd': - /* toggle debug flag */ - kdebug ^= 1; - break; - - case 'g': /* return the value of the CPU registers. - * some of them are non-PowerPC names :( - * they are stored in gdb like: - * struct { - * u32 gpr[32]; - * f64 fpr[32]; - * u32 pc, ps, cnd, lr; (ps=msr) - * u32 cnt, xer, mq; - * } - */ - { - int i; - ptr = remcomOutBuffer; - /* General Purpose Regs */ - ptr = mem2hex((char *)regs, ptr, 32 * 4); - /* Floating Point Regs - FIXME */ - /*ptr = mem2hex((char *), ptr, 32 * 8);*/ - for(i=0; i<(32*8*2); i++) { /* 2chars/byte */ - ptr[i] = '0'; - } - ptr += 32*8*2; - /* pc, msr, cr, lr, ctr, xer, (mq is unused) */ - ptr = mem2hex((char *)®s->nip, ptr, 4); - ptr = mem2hex((char *)®s->msr, ptr, 4); - ptr = mem2hex((char *)®s->ccr, ptr, 4); - ptr = mem2hex((char *)®s->link, ptr, 4); - ptr = mem2hex((char *)®s->ctr, ptr, 4); - ptr = mem2hex((char *)®s->xer, ptr, 4); - } - break; - - case 'G': /* set the value of the CPU registers */ - { - ptr = &remcomInBuffer[1]; - - /* - * If the stack pointer has moved, you should pray. - * (cause only god can help you). - */ - - /* General Purpose Regs */ - hex2mem(ptr, (char *)regs, 32 * 4); - - /* Floating Point Regs - FIXME?? */ - /*ptr = hex2mem(ptr, ??, 32 * 8);*/ - ptr += 32*8*2; - - /* pc, msr, cr, lr, ctr, xer, (mq is unused) */ - ptr = hex2mem(ptr, (char *)®s->nip, 4); - ptr = hex2mem(ptr, (char *)®s->msr, 4); - ptr = hex2mem(ptr, (char *)®s->ccr, 4); - ptr = hex2mem(ptr, (char *)®s->link, 4); - ptr = hex2mem(ptr, (char *)®s->ctr, 4); - ptr = hex2mem(ptr, (char *)®s->xer, 4); - - strcpy(remcomOutBuffer,"OK"); - } - break; - case 'H': - /* don't do anything, yet, just acknowledge */ - hexToInt(&ptr, &addr); - strcpy(remcomOutBuffer,"OK"); - break; - - case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ - /* Try to read %x,%x. */ - - ptr = &remcomInBuffer[1]; - - if (hexToInt(&ptr, &addr) - && *ptr++ == ',' - && hexToInt(&ptr, &length)) { - if (mem2hex((char *)addr, remcomOutBuffer,length)) - break; - strcpy (remcomOutBuffer, "E03"); - } else { - strcpy(remcomOutBuffer,"E01"); - } - break; - - case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ - /* Try to read '%x,%x:'. */ - - ptr = &remcomInBuffer[1]; - - if (hexToInt(&ptr, &addr) - && *ptr++ == ',' - && hexToInt(&ptr, &length) - && *ptr++ == ':') { - if (hex2mem(ptr, (char *)addr, length)) { - strcpy(remcomOutBuffer, "OK"); - } else { - strcpy(remcomOutBuffer, "E03"); - } - flush_icache_range(addr, addr+length); - } else { - strcpy(remcomOutBuffer, "E02"); - } - break; - - - case 'k': /* kill the program, actually just continue */ - case 'c': /* cAA..AA Continue; address AA..AA optional */ - /* try to read optional parameter, pc unchanged if no parm */ - - ptr = &remcomInBuffer[1]; - if (hexToInt(&ptr, &addr)) { - regs->nip = addr; - } - -/* Need to flush the instruction cache here, as we may have deposited a - * breakpoint, and the icache probably has no way of knowing that a data ref to - * some location may have changed something that is in the instruction cache. - */ - kgdb_flush_cache_all(); - set_msr(msr); - kgdb_interruptible(1); - unlock_kernel(); - kgdb_active = 0; - return; - - case 's': - kgdb_flush_cache_all(); - regs->msr |= MSR_SE; -#if 0 - set_msr(msr | MSR_SE); -#endif - unlock_kernel(); - kgdb_active = 0; - return; - - case 'r': /* Reset (if user process..exit ???)*/ - panic("kgdb reset."); - break; - } /* switch */ - if (remcomOutBuffer[0] && kdebug) { - printk("remcomInBuffer: %s\n", remcomInBuffer); - printk("remcomOutBuffer: %s\n", remcomOutBuffer); - } - /* reply to the request */ - putpacket(remcomOutBuffer); - } /* while(1) */ -} - -/* This function will generate a breakpoint exception. It is used at the - beginning of a program to sync up with a debugger and can be used - otherwise as a quick means to stop program execution and "break" into - the debugger. */ - -void -breakpoint(void) -{ - if (!initialized) { - printk("breakpoint() called b4 kgdb init\n"); - return; - } - - asm(" .globl breakinst - breakinst: .long 0x7d821008 - "); -} - -/* Output string in GDB O-packet format if GDB has connected. If nothing - output, returns 0 (caller must then handle output). */ -int -kgdb_output_string (const char* s, unsigned int count) -{ - char buffer[512]; - - if (!kgdb_started) - return 0; - - count = (count <= (sizeof(buffer) / 2 - 2)) - ? count : (sizeof(buffer) / 2 - 2); - - buffer[0] = 'O'; - mem2hex (s, &buffer[1], count); - putpacket(buffer); - - return 1; - } diff -Nru a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c --- a/arch/ppc64/kernel/ppc_ksyms.c Sun Jun 2 18:44:56 2002 +++ b/arch/ppc64/kernel/ppc_ksyms.c Sun Jun 2 18:44:56 2002 @@ -257,7 +257,7 @@ EXPORT_SYMBOL(xmon); #endif -#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) +#ifdef CONFIG_DEBUG_KERNEL extern void (*debugger)(struct pt_regs *regs); extern int (*debugger_bpt)(struct pt_regs *regs); extern int (*debugger_sstep)(struct pt_regs *regs); diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c --- a/arch/ppc64/kernel/process.c Sun Jun 2 18:44:56 2002 +++ b/arch/ppc64/kernel/process.c Sun Jun 2 18:44:56 2002 @@ -117,7 +117,6 @@ regs->msr&MSR_DR ? 1 : 0); printk("TASK = %p[%d] '%s' ", current, current->pid, current->comm); - printk("Last syscall: %ld ", current->thread.last_syscall); printk("\nlast math %p ", last_task_used_math); #ifdef CONFIG_SMP @@ -222,8 +221,6 @@ } memcpy(&p->thread.fpr, ¤t->thread.fpr, sizeof(p->thread.fpr)); p->thread.fpscr = current->thread.fpscr; - - p->thread.last_syscall = -1; return 0; } diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Sun Jun 2 18:44:58 2002 +++ b/arch/ppc64/kernel/prom.c Sun Jun 2 18:44:58 2002 @@ -878,7 +878,7 @@ phandle node; ihandle phb_node; unsigned long offset = reloc_offset(); - char compatible[64], path[64], type[64]; + char compatible[64], path[64], type[64], model[64]; unsigned long i, table = 0; unsigned long base, vbase, align; unsigned int minalign, minsize; @@ -893,16 +893,25 @@ for (node = 0; prom_next_node(&node); ) { compatible[0] = 0; type[0] = 0; + model[0] = 0; call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"), compatible, sizeof(compatible)); call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"), type, sizeof(type)); + call_prom(RELOC("getprop"), 4, 1, node, RELOC("model"), + model, sizeof(model)); - if ((compatible[0] == 0) || - ((strstr(compatible, RELOC("python")) == NULL) && - (strstr(compatible, RELOC("Speedwagon")) == NULL))) { - continue; + /* Keep the old logic in tack to avoid regression. */ + if (compatible[0] != 0) { + if((strstr(compatible, RELOC("python")) == NULL) && + (strstr(compatible, RELOC("Speedwagon")) == NULL)) + continue; + } else if (model[0] != 0) { + if ((strstr(model, RELOC("ython")) == NULL) && + (strstr(model, RELOC("peedwagon")) == NULL)) + continue; } + if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL)) { continue; } diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c --- a/arch/ppc64/kernel/setup.c Sun Jun 2 18:44:57 2002 +++ b/arch/ppc64/kernel/setup.c Sun Jun 2 18:44:57 2002 @@ -130,6 +130,14 @@ /* This should be fixed properly in kernel/resource.c */ iomem_resource.end = MEM_SPACE_LIMIT; +#ifdef CONFIG_XMON_DEFAULT + debugger = xmon; + debugger_bpt = xmon_bpt; + debugger_sstep = xmon_sstep; + debugger_iabr_match = xmon_iabr_match; + debugger_dabr_match = xmon_dabr_match; +#endif + /* pSeries systems are identified in prom.c via OF. */ if ( itLpNaca.xLparInstalled == 1 ) naca->platform = PLATFORM_ISERIES_LPAR; @@ -371,10 +379,15 @@ #endif cmd_line[0] = 0; + +#ifdef CONFIG_CMDLINE + strcpy(cmd_line, CONFIG_CMDLINE); +#endif /* CONFIG_CMDLINE */ + chosen = find_devices("chosen"); if (chosen != NULL) { p = get_property(chosen, "bootargs", NULL); - if (p != NULL) + if (p != NULL && p[0] != 0) strncpy(cmd_line, p, sizeof(cmd_line)); } cmd_line[sizeof(cmd_line) - 1] = 0; @@ -507,11 +520,6 @@ ppc_md.progress("setup_arch:enter", 0x3eab); -#if defined(CONFIG_KGDB) - kgdb_map_scc(); - set_debug_traps(); - breakpoint(); -#endif /* * Set cache line size based on type of cpu as a default. * Systems with OF can look in the properties on the cpu node(s) @@ -541,26 +549,6 @@ paging_init(); sort_exception_table(); ppc_md.progress("setup_arch: exit", 0x3eab); -} - -void exception_trace(unsigned long trap) -{ - unsigned long x, srr0, srr1, reg20, reg1, reg21; - - asm("mflr %0" : "=r" (x) :); - asm("mfspr %0,0x1a" : "=r" (srr0) :); - asm("mfspr %0,0x1b" : "=r" (srr1) :); - asm("mr %0,1" : "=r" (reg1) :); - asm("mr %0,20" : "=r" (reg20) :); - asm("mr %0,21" : "=r" (reg21) :); - - udbg_puts("\n"); - udbg_puts("Took an exception : "); udbg_puthex(x); udbg_puts("\n"); - udbg_puts(" "); udbg_puthex(reg1); udbg_puts("\n"); - udbg_puts(" "); udbg_puthex(reg20); udbg_puts("\n"); - udbg_puts(" "); udbg_puthex(reg21); udbg_puts("\n"); - udbg_puts(" "); udbg_puthex(srr0); udbg_puts("\n"); - udbg_puts(" "); udbg_puthex(srr1); udbg_puts("\n"); } int set_spread_lpevents( char * str ) diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c --- a/arch/ppc64/kernel/signal.c Sun Jun 2 18:44:56 2002 +++ b/arch/ppc64/kernel/signal.c Sun Jun 2 18:44:56 2002 @@ -1,8 +1,6 @@ /* * linux/arch/ppc64/kernel/signal.c * - * - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * @@ -72,11 +70,6 @@ struct pt_regs *regs) { sigset_t saveset; - - PPCDBG(PPCDBG_SYS64X, "sys_sigsuspend - running - pid=%ld current=%lx comm=%s \n", - current->pid, current, current->comm); - - mask &= _BLOCKABLE; spin_lock_irq(¤t->sigmask_lock); @@ -107,11 +100,7 @@ { sigset_t saveset, newset; - - PPCDBG(PPCDBG_SYS64X, "sys_rt_sigsuspend - running - pid=%ld current=%lx comm=%s \n", - current->pid, current, current->comm); - - /* XXX: Don't preclude handling different sized sigset_t's. */ + /* XXX: Don't preclude handling different sized sigset_t's. */ if (sigsetsize != sizeof(sigset_t)) return -EINVAL; @@ -136,14 +125,10 @@ -asmlinkage long sys_sigaltstack(const stack_t *uss, stack_t *uoss) +long sys_sigaltstack(const stack_t *uss, stack_t *uoss) { - struct pt_regs *regs = (struct pt_regs *) &uss; - - PPCDBG(PPCDBG_SYS64X, "sys_sigaltstack - running - pid=%ld current=%lx comm=%s \n", - current->pid, current, current->comm); - - return do_sigaltstack(uss, uoss, regs->gpr[1]); + struct pt_regs *regs = (struct pt_regs *) &uss; + return do_sigaltstack(uss, uoss, regs->gpr[1]); } long sys_sigaction(int sig, const struct old_sigaction *act, @@ -152,11 +137,6 @@ struct k_sigaction new_ka, old_ka; int ret; - PPCDBG(PPCDBG_SYS64X, "sys_sigaction - running - pid=%ld current=%lx comm=%s \n", - current->pid, current, current->comm); - - - if (act) { old_sigset_t mask; if (verify_area(VERIFY_READ, act, sizeof(*act)) || @@ -168,7 +148,7 @@ siginitset(&new_ka.sa.sa_mask, mask); } - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + ret = do_sigaction(sig, (act? &new_ka: NULL), (oact? &old_ka: NULL)); if (!ret && oact) { if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || @@ -179,9 +159,6 @@ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } - - - return ret; } @@ -189,13 +166,11 @@ * When we have signals to deliver, we set up on the * user stack, going down from the original stack pointer: * a sigregs struct - * one or more sigcontext structs + * one or more sigcontext structs with * a gap of __SIGNAL_FRAMESIZE bytes * * Each of these things must be a multiple of 16 bytes in size. * - * XXX ultimately we will have to stack up a siginfo and ucontext - * for each rt signal. */ struct sigregs { elf_gregset_t gp_regs; @@ -206,8 +181,6 @@ int abigap[72]; }; - - struct rt_sigframe { unsigned long _unused[2]; @@ -236,11 +209,9 @@ struct rt_sigframe *rt_sf; struct sigcontext_struct sigctx; struct sigregs *sr; - int ret; elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ sigset_t set; stack_t st; - unsigned long prevsp; rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)) @@ -252,53 +223,29 @@ current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sigmask_lock); + if (regs->msr & MSR_FP) + giveup_fpu(current); - rt_sf++; /* Look at next rt_sigframe */ - if (rt_sf == (struct rt_sigframe *)(sigctx.regs)) { - /* Last stacked signal - restore registers - - * sigctx is initialized to point to the - * preamble frame (where registers are stored) - * see handle_signal() - */ - sr = (struct sigregs *) sigctx.regs; - if (regs->msr & MSR_FP ) - giveup_fpu(current); - if (copy_from_user(saved_regs, &sr->gp_regs, - sizeof(sr->gp_regs))) - goto badframe; - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - saved_regs[PT_SOFTE] = regs->softe; - memcpy(regs, saved_regs, GP_REGS_SIZE); - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) - goto badframe; - /* This function sets back the stack flags into - the current task structure. */ - sys_sigaltstack(&st, NULL); + /* restore registers - + * sigctx is initialized to point to the + * preamble frame (where registers are stored) + * see handle_signal() + */ + sr = (struct sigregs *) sigctx.regs; + if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) + goto badframe; + saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) + | (saved_regs[PT_MSR] & MSR_USERCHANGE); + saved_regs[PT_SOFTE] = regs->softe; + memcpy(regs, saved_regs, GP_REGS_SIZE); + if (copy_from_user(current->thread.fpr, &sr->fp_regs, + sizeof(sr->fp_regs))) + goto badframe; + /* This function sets back the stack flags into + the current task structure. */ + sys_sigaltstack(&st, NULL); - ret = regs->result; - } else { - /* More signals to go */ - /* Set up registers for next signal handler */ - regs->gpr[1] = (unsigned long)rt_sf - __SIGNAL_FRAMESIZE; - if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx))) - goto badframe; - sr = (struct sigregs *) sigctx.regs; - regs->gpr[3] = ret = sigctx.signal; - /* Get the siginfo */ - get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo); - /* Get the ucontext */ - get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc); - regs->gpr[6] = (unsigned long) rt_sf; - - regs->link = (unsigned long) &sr->tramp; - regs->nip = sigctx.handler; - if (get_user(prevsp, &sr->gp_regs[PT_R1]) - || put_user(prevsp, (unsigned long *) regs->gpr[1])) - goto badframe; - } - return ret; + return regs->result; badframe: do_exit(SIGSEGV); @@ -335,6 +282,7 @@ goto badframe; flush_icache_range((unsigned long) &frame->tramp[0], (unsigned long) &frame->tramp[2]); + current->thread.fpscr = 0; /* turn off all fp exceptions */ /* Retrieve rt_sigframe from stack and set up registers for signal handler @@ -359,7 +307,6 @@ regs->gpr[6] = (unsigned long) rt_sf; regs->link = (unsigned long) frame->tramp; - return; badframe: @@ -379,12 +326,10 @@ { struct sigcontext_struct *sc, sigctx; struct sigregs *sr; - long ret; elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ sigset_t set; - unsigned long prevsp; - sc = (struct sigcontext_struct *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); + sc = (struct sigcontext_struct *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); if (copy_from_user(&sigctx, sc, sizeof(sigctx))) goto badframe; @@ -397,43 +342,23 @@ current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sigmask_lock); + if (regs->msr & MSR_FP ) + giveup_fpu(current); - sc++; /* Look at next sigcontext */ - if (sc == (struct sigcontext_struct *)(sigctx.regs)) { - /* Last stacked signal - restore registers */ - sr = (struct sigregs *) sigctx.regs; - if (regs->msr & MSR_FP ) - giveup_fpu(current); - if (copy_from_user(saved_regs, &sr->gp_regs, - sizeof(sr->gp_regs))) - goto badframe; - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - saved_regs[PT_SOFTE] = regs->softe; - memcpy(regs, saved_regs, GP_REGS_SIZE); - - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) - goto badframe; - - ret = regs->result; + /* restore registers */ + sr = (struct sigregs *) sigctx.regs; + if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) + goto badframe; + saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) + | (saved_regs[PT_MSR] & MSR_USERCHANGE); + saved_regs[PT_SOFTE] = regs->softe; + memcpy(regs, saved_regs, GP_REGS_SIZE); - } else { - /* More signals to go */ - regs->gpr[1] = (unsigned long)sc - __SIGNAL_FRAMESIZE; - if (copy_from_user(&sigctx, sc, sizeof(sigctx))) - goto badframe; - sr = (struct sigregs *) sigctx.regs; - regs->gpr[3] = ret = sigctx.signal; - regs->gpr[4] = (unsigned long) sc; - regs->link = (unsigned long) &sr->tramp; - regs->nip = sigctx.handler; + if (copy_from_user(current->thread.fpr, &sr->fp_regs, + sizeof(sr->fp_regs))) + goto badframe; - if (get_user(prevsp, &sr->gp_regs[PT_R1]) - || put_user(prevsp, (unsigned long *) regs->gpr[1])) - goto badframe; - } - return ret; + return regs->result; badframe: do_exit(SIGSEGV); @@ -444,7 +369,7 @@ */ static void setup_frame(struct pt_regs *regs, struct sigregs *frame, - unsigned long newsp) + unsigned long newsp) { /* Handler is *really* a pointer to the function descriptor for @@ -474,6 +399,7 @@ goto badframe; flush_icache_range((unsigned long) &frame->tramp[0], (unsigned long) &frame->tramp[2]); + current->thread.fpscr = 0; /* turn off all fp exceptions */ newsp -= __SIGNAL_FRAMESIZE; if ( get_user(temp_ptr, &sc->handler)) @@ -490,14 +416,9 @@ regs->gpr[4] = (unsigned long) sc; regs->link = (unsigned long) frame->tramp; - - PPCDBG(PPCDBG_SIGNAL, "setup_frame - returning - regs->gpr[1]=%lx, regs->gpr[4]=%lx, regs->link=%lx \n", - regs->gpr[1], regs->gpr[4], regs->link); - return; - badframe: - PPCDBG(PPCDBG_SIGNAL, "setup_frame - badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); PPCDBG_ENTER_DEBUGGER(); +badframe: #if DEBUG_SIG printk("badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); @@ -513,7 +434,7 @@ struct pt_regs * regs, unsigned long *newspp, unsigned long frame) { struct sigcontext_struct *sc; - struct rt_sigframe *rt_sf; + struct rt_sigframe *rt_sf; struct k_sigaction *ka = ¤t->sig->action[sig-1]; if (regs->trap == 0x0C00 /* System Call! */ @@ -521,21 +442,20 @@ ((int)regs->result == -ERESTARTSYS && !(ka->sa.sa_flags & SA_RESTART)))) regs->result = -EINTR; - /* Set up Signal Frame */ - + + /* Set up Signal Frame */ if (ka->sa.sa_flags & SA_SIGINFO) { /* Put a Real Time Context onto stack */ *newspp -= sizeof(*rt_sf); rt_sf = (struct rt_sigframe *) *newspp; if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf))) goto badframe; - if (__put_user((unsigned long) ka->sa.sa_handler, &rt_sf->uc.uc_mcontext.handler) || __put_user(&rt_sf->info, &rt_sf->pinfo) || __put_user(&rt_sf->uc, &rt_sf->puc) /* Put the siginfo */ - || __copy_to_user(&rt_sf->info, info, sizeof(*info)) + || copy_siginfo_to_user(&rt_sf->info, info) /* Create the ucontext */ || __put_user(0, &rt_sf->uc.uc_flags) || __put_user(0, &rt_sf->uc.uc_link) @@ -548,22 +468,21 @@ || __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs) || __put_user(sig, &rt_sf->uc.uc_mcontext.signal)) goto badframe; - } else { - /* Put another sigcontext on the stack */ - *newspp -= sizeof(*sc); - sc = (struct sigcontext_struct *) *newspp; - if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) - goto badframe; - - if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler) - || __put_user(oldset->sig[0], &sc->oldmask) + /* Put a sigcontext on the stack */ + *newspp -= sizeof(*sc); + sc = (struct sigcontext_struct *) *newspp; + if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) + goto badframe; + + if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler) + || __put_user(oldset->sig[0], &sc->oldmask) #if _NSIG_WORDS > 1 - || __put_user(oldset->sig[1], &sc->_unused[3]) + || __put_user(oldset->sig[1], &sc->_unused[3]) #endif - || __put_user((struct pt_regs *)frame, &sc->regs) - || __put_user(sig, &sc->signal)) - goto badframe; + || __put_user((struct pt_regs *)frame, &sc->regs) + || __put_user(sig, &sc->signal)) + goto badframe; } if (ka->sa.sa_flags & SA_ONESHOT) @@ -623,34 +542,24 @@ newsp = frame = newsp - sizeof(struct sigregs); /* Whee! Actually deliver the signal. */ - - PPCDBG(PPCDBG_SIGNAL, "do_signal - GOING TO RUN SIGNAL HANDLER - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm); handle_signal(signr, &info, oldset, regs, &newsp, frame); - PPCDBG(PPCDBG_SIGNAL, "do_signal - after running signal handler - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm); } if (regs->trap == 0x0C00 /* System Call! */ && ((int)regs->result == -ERESTARTNOHAND || (int)regs->result == -ERESTARTSYS || (int)regs->result == -ERESTARTNOINTR)) { - PPCDBG(PPCDBG_SIGNAL, "do_signal - going to back up & retry system call \n"); regs->gpr[3] = regs->orig_gpr3; regs->nip -= 4; /* Back up & retry system call */ regs->result = 0; } if (newsp == frame) - { - PPCDBG(PPCDBG_SIGNAL, "do_signal - returning w/ no signal delivered \n"); - return 0; /* no signals delivered */ - } - - + return 0; /* no signals delivered */ - if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(regs, (struct sigregs *) frame, newsp); - else - setup_frame(regs, (struct sigregs *) frame, newsp); - PPCDBG(PPCDBG_SIGNAL, "do_signal - returning a signal was delivered \n"); + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(regs, (struct sigregs *) frame, newsp); + else + setup_frame(regs, (struct sigregs *) frame, newsp); return 1; } diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c --- a/arch/ppc64/kernel/signal32.c Sun Jun 2 18:44:58 2002 +++ b/arch/ppc64/kernel/signal32.c Sun Jun 2 18:44:58 2002 @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -72,79 +71,78 @@ }; struct sigregs32 { - /***********************************************************************/ - /* the gp_regs array is 32 bit representation of the pt_regs structure */ - /* that was stored on the kernle stack during the system call that */ - /* was interrupted for the signal. */ - /* */ - /* Note that the entire pt_regs regs structure will fit in the gp_regs */ - /* structure because the ELF_NREG value is 48 for PPC and the pt_regs*/ - /* structure contains 44 registers */ - /* */ - /***********************************************************************/ + /* + * the gp_regs array is 32 bit representation of the pt_regs + * structure that was stored on the kernle stack during the + * system call that was interrupted for the signal. + * + * Note that the entire pt_regs regs structure will fit in + * the gp_regs structure because the ELF_NREG value is 48 for + * PPC and the pt_regs structure contains 44 registers + */ elf_gregset_t32 gp_regs; double fp_regs[ELF_NFPREG]; unsigned int tramp[2]; - /* Programs using the rs6000/xcoff abi can save up to 19 gp regs - and 18 fp regs below sp before decrementing it. */ + /* + * Programs using the rs6000/xcoff abi can save up to 19 gp + * regs and 18 fp regs below sp before decrementing it. + */ int abigap[56]; }; struct rt_sigframe_32 { - /* Unused space at start of frame to allow for storing of stack pointers */ + /* + * Unused space at start of frame to allow for storing of + * stack pointers + */ unsigned long _unused; - /* This is a 32 bit pointer in user address space - * it is a pointer to the siginfo stucture in the rt stack frame + /* + * This is a 32 bit pointer in user address space + * it is a pointer to the siginfo stucture in the rt stack frame */ u32 pinfo; - /* This is a 32 bit pointer in user address space */ - /* it is a pointer to the user context in the rt stack frame */ + /* + * This is a 32 bit pointer in user address space + * it is a pointer to the user context in the rt stack frame + */ u32 puc; struct siginfo32 info; struct ucontext32 uc; }; +extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, + int options, struct rusage * ru); +/* + * Start of nonRT signal support + * + * sigset_t is 32 bits for non-rt signals + * + * System Calls + * sigaction sys32_sigaction + * sigpending sys32_sigpending + * sigprocmask sys32_sigprocmask + * sigreturn sys32_sigreturn + * + * Note sigsuspend has no special 32 bit routine - uses the 64 bit routine + * + * Other routines + * setup_frame32 + */ -extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru); - - -/****************************************************************************/ -/* Start of nonRT signal support */ -/* */ -/* sigset_t is 32 bits for non-rt signals */ -/* */ -/* System Calls */ -/* sigaction sys32_sigaction */ -/* sigpending sys32_sigpending */ -/* sigprocmask sys32_sigprocmask */ -/* sigreturn sys32_sigreturn */ -/* */ -/* Note sigsuspend has no special 32 bit routine - uses the 64 bit routine */ -/* */ -/* Other routines */ -/* setup_frame32 */ -/* */ -/****************************************************************************/ - - -asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact) +asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 *act, + struct old_sigaction32 *oact) { struct k_sigaction new_ka, old_ka; int ret; - PPCDBG(PPCDBG_SYS32, "sys32_sigaction - entered - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm); - if (sig < 0) - { sig = -sig; - } - if (act) - { + if (act) { old_sigset_t32 mask; ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler); @@ -153,24 +151,17 @@ ret |= __get_user(mask, &act->sa_mask); if (ret) return ret; - PPCDBG(PPCDBG_SIGNAL, "sys32_sigaction flags =%lx \n", new_ka.sa.sa_flags); - siginitset(&new_ka.sa.sa_mask, mask); } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) - { + if (!ret && oact) { ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler); ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer); ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } - - PPCDBG(PPCDBG_SYS32, "sys32_sigaction - exited - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm); - return ret; } @@ -184,46 +175,44 @@ old_sigset_t s; int ret; mm_segment_t old_fs = get_fs(); - - PPCDBG(PPCDBG_SYS32, "sys32_sigpending - entered - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm); - - set_fs (KERNEL_DS); - ret = sys_sigpending(&s); - set_fs (old_fs); - if (put_user (s, set)) return -EFAULT; - - PPCDBG(PPCDBG_SYS32, "sys32_sigpending - exited - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm); + set_fs(KERNEL_DS); + ret = sys_sigpending(&s); + set_fs(old_fs); + if (put_user(s, set)) + return -EFAULT; return ret; } -extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset); +extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set, + old_sigset_t *oset); -/* Note: it is necessary to treat how as an unsigned int, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. +/* + * Note: it is necessary to treat how as an unsigned int, with the + * corresponding cast to a signed int to insure that the proper + * conversion (sign extension) between the register representation + * of a signed int (msr in 32-bit mode) and the register representation + * of a signed int (msr in 64-bit mode) is performed. */ -asmlinkage long sys32_sigprocmask(u32 how, old_sigset_t32 *set, old_sigset_t32 *oset) +asmlinkage long sys32_sigprocmask(u32 how, old_sigset_t32 *set, + old_sigset_t32 *oset) { old_sigset_t s; int ret; mm_segment_t old_fs = get_fs(); - - PPCDBG(PPCDBG_SYS32, "sys32_sigprocmask - entered - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm); - - if (set && get_user (s, set)) return -EFAULT; - set_fs (KERNEL_DS); - ret = sys_sigprocmask((int)how, set ? &s : NULL, oset ? &s : NULL); - set_fs (old_fs); - if (ret) return ret; - if (oset && put_user (s, oset)) return -EFAULT; - - PPCDBG(PPCDBG_SYS32, "sys32_sigprocmask - exited - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm); + if (set && get_user(s, set)) + return -EFAULT; + set_fs(KERNEL_DS); + ret = sys_sigprocmask((int)how, set ? &s : NULL, oset ? &s : NULL); + set_fs(old_fs); + if (ret) + return ret; + if (oset && put_user (s, oset)) + return -EFAULT; return 0; } @@ -238,7 +227,7 @@ * * Each of these things must be a multiple of 16 bytes in size. * -*/ + */ /* @@ -253,16 +242,16 @@ int ret; elf_gregset_t32 saved_regs; /* an array of ELF_NGREG unsigned ints (32 bits) */ sigset_t set; - unsigned int prevsp; - - PPCDBG(PPCDBG_SIGNAL, "sys32_sigreturn - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm); + int i; sc = (struct sigcontext32_struct *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32); if (copy_from_user(&sigctx, sc, sizeof(sigctx))) goto badframe; - /* Note that PPC32 puts the upper 32 bits of the sigmask in the */ - /* unused part of the signal stackframe */ + /* + * Note that PPC32 puts the upper 32 bits of the sigmask in the + * unused part of the signal stackframe + */ set.sig[0] = sigctx.oldmask + ((long)(sigctx._unused[3])<< 32); sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); @@ -270,215 +259,132 @@ recalc_sigpending(); spin_unlock_irq(¤t->sigmask_lock); - sc++; /* Look at next sigcontext */ - /* If the next sigcontext is actually the sigregs (frame) */ - /* - then no more sigcontexts on the user stack */ - if (sc == (struct sigcontext32_struct*)(u64)sigctx.regs) - { - /* Last stacked signal - restore registers */ - sr = (struct sigregs32*)(u64)sigctx.regs; - if (regs->msr & MSR_FP ) - giveup_fpu(current); - /* copy the 32 bit register values off the user stack */ - /* into the 32 bit register area */ - if (copy_from_user(saved_regs, &sr->gp_regs,sizeof(sr->gp_regs))) - goto badframe; - /**********************************************************************/ - /* The saved reg structure in the frame is an elf_grepset_t32, it is */ - /* a 32 bit register save of the registers in the pt_regs structure */ - /* that was stored on the kernel stack during the system call */ - /* when the system call was interrupted for the signal. Only 32 bits*/ - /* are saved because the sigcontext contains a pointer to the regs */ - /* and the sig context address is passed as a pointer to the signal */ - /* handler. */ - /* */ - /* The entries in the elf_grepset have the same index as the elements */ - /* in the pt_regs structure. */ - /* */ - /**********************************************************************/ - - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - regs->gpr[0] = (u64)(saved_regs[0]) & 0xFFFFFFFF; - regs->gpr[1] = (u64)(saved_regs[1]) & 0xFFFFFFFF; - /**********************************************************************/ - /* Register 2 is the kernel toc - should be reset on any calls into */ - /* the kernel */ - /**********************************************************************/ - regs->gpr[2] = (u64)(saved_regs[2]) & 0xFFFFFFFF; - - regs->gpr[3] = (u64)(saved_regs[3]) & 0xFFFFFFFF; - regs->gpr[4] = (u64)(saved_regs[4]) & 0xFFFFFFFF; - regs->gpr[5] = (u64)(saved_regs[5]) & 0xFFFFFFFF; - regs->gpr[6] = (u64)(saved_regs[6]) & 0xFFFFFFFF; - regs->gpr[7] = (u64)(saved_regs[7]) & 0xFFFFFFFF; - regs->gpr[8] = (u64)(saved_regs[8]) & 0xFFFFFFFF; - regs->gpr[9] = (u64)(saved_regs[9]) & 0xFFFFFFFF; - regs->gpr[10] = (u64)(saved_regs[10]) & 0xFFFFFFFF; - regs->gpr[11] = (u64)(saved_regs[11]) & 0xFFFFFFFF; - regs->gpr[12] = (u64)(saved_regs[12]) & 0xFFFFFFFF; - regs->gpr[13] = (u64)(saved_regs[13]) & 0xFFFFFFFF; - regs->gpr[14] = (u64)(saved_regs[14]) & 0xFFFFFFFF; - regs->gpr[15] = (u64)(saved_regs[15]) & 0xFFFFFFFF; - regs->gpr[16] = (u64)(saved_regs[16]) & 0xFFFFFFFF; - regs->gpr[17] = (u64)(saved_regs[17]) & 0xFFFFFFFF; - regs->gpr[18] = (u64)(saved_regs[18]) & 0xFFFFFFFF; - regs->gpr[19] = (u64)(saved_regs[19]) & 0xFFFFFFFF; - regs->gpr[20] = (u64)(saved_regs[20]) & 0xFFFFFFFF; - regs->gpr[21] = (u64)(saved_regs[21]) & 0xFFFFFFFF; - regs->gpr[22] = (u64)(saved_regs[22]) & 0xFFFFFFFF; - regs->gpr[23] = (u64)(saved_regs[23]) & 0xFFFFFFFF; - regs->gpr[24] = (u64)(saved_regs[24]) & 0xFFFFFFFF; - regs->gpr[25] = (u64)(saved_regs[25]) & 0xFFFFFFFF; - regs->gpr[26] = (u64)(saved_regs[26]) & 0xFFFFFFFF; - regs->gpr[27] = (u64)(saved_regs[27]) & 0xFFFFFFFF; - regs->gpr[28] = (u64)(saved_regs[28]) & 0xFFFFFFFF; - regs->gpr[29] = (u64)(saved_regs[29]) & 0xFFFFFFFF; - regs->gpr[30] = (u64)(saved_regs[30]) & 0xFFFFFFFF; - regs->gpr[31] = (u64)(saved_regs[31]) & 0xFFFFFFFF; - /****************************************************/ - /* restore the non gpr registers */ - /****************************************************/ - regs->msr = (u64)(saved_regs[PT_MSR]) & 0xFFFFFFFF; - /* Insure that the interrupt mode is 64 bit, during 32 bit execution. - * (This is necessary because we only saved lower 32 bits of msr.) - */ - regs->msr = regs->msr | MSR_ISF; /* When this thread is interrupted it should run in 64 bit mode. */ + /* Last stacked signal - restore registers */ + sr = (struct sigregs32*)(u64)sigctx.regs; + if (regs->msr & MSR_FP ) + giveup_fpu(current); + /* + * copy the 32 bit register values off the user stack + * into the 32 bit register area + */ + if (copy_from_user(saved_regs, &sr->gp_regs, + sizeof(sr->gp_regs))) + goto badframe; + /* + * The saved reg structure in the frame is an elf_grepset_t32, + * it is a 32 bit register save of the registers in the + * pt_regs structure that was stored on the kernel stack + * during the system call when the system call was interrupted + * for the signal. Only 32 bits are saved because the + * sigcontext contains a pointer to the regs and the sig + * context address is passed as a pointer to the signal + * handler. + * + * The entries in the elf_grepset have the same index as the + * elements in the pt_regs structure. + */ + saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) + | (saved_regs[PT_MSR] & MSR_USERCHANGE); + /* + * Register 2 is the kernel toc - should be reset on + * any calls into the kernel + */ + for (i = 0; i < 32; i++) + regs->gpr[i] = (u64)(saved_regs[i]) & 0xFFFFFFFF; - regs->nip = (u64)(saved_regs[PT_NIP]) & 0xFFFFFFFF; - regs->orig_gpr3 = (u64)(saved_regs[PT_ORIG_R3]) & 0xFFFFFFFF; - regs->ctr = (u64)(saved_regs[PT_CTR]) & 0xFFFFFFFF; - regs->link = (u64)(saved_regs[PT_LNK]) & 0xFFFFFFFF; - regs->xer = (u64)(saved_regs[PT_XER]) & 0xFFFFFFFF; - regs->ccr = (u64)(saved_regs[PT_CCR]) & 0xFFFFFFFF; - /* regs->softe is left unchanged (like the MSR.EE bit) */ - /******************************************************/ - /* the DAR and the DSISR are only relevant during a */ - /* data or instruction storage interrupt. The value */ - /* will be set to zero. */ - /******************************************************/ - regs->dar = 0; - regs->dsisr = 0; - regs->result = (u64)(saved_regs[PT_RESULT]) & 0xFFFFFFFF; + /* + * restore the non gpr registers + */ + regs->msr = (u64)(saved_regs[PT_MSR]) & 0xFFFFFFFF; + /* + * Insure that the interrupt mode is 64 bit, during 32 bit + * execution. (This is necessary because we only saved + * lower 32 bits of msr.) + */ + regs->msr = regs->msr | MSR_ISF; /* When this thread is interrupted it should run in 64 bit mode. */ - if (copy_from_user(current->thread.fpr, &sr->fp_regs, sizeof(sr->fp_regs))) - goto badframe; + regs->nip = (u64)(saved_regs[PT_NIP]) & 0xFFFFFFFF; + regs->orig_gpr3 = (u64)(saved_regs[PT_ORIG_R3]) & 0xFFFFFFFF; + regs->ctr = (u64)(saved_regs[PT_CTR]) & 0xFFFFFFFF; + regs->link = (u64)(saved_regs[PT_LNK]) & 0xFFFFFFFF; + regs->xer = (u64)(saved_regs[PT_XER]) & 0xFFFFFFFF; + regs->ccr = (u64)(saved_regs[PT_CCR]) & 0xFFFFFFFF; + /* regs->softe is left unchanged (like the MSR.EE bit) */ + /******************************************************/ + /* the DAR and the DSISR are only relevant during a */ + /* data or instruction storage interrupt. The value */ + /* will be set to zero. */ + /******************************************************/ + regs->dar = 0; + regs->dsisr = 0; + regs->result = (u64)(saved_regs[PT_RESULT]) & 0xFFFFFFFF; - ret = regs->result; - } else { - /* More signals to go */ - regs->gpr[1] = (unsigned long)sc - __SIGNAL_FRAMESIZE32; - if (copy_from_user(&sigctx, sc, sizeof(sigctx))) - goto badframe; - sr = (struct sigregs32*)(u64)sigctx.regs; - regs->gpr[3] = ret = sigctx.signal; - regs->gpr[4] = (unsigned long) sc; - regs->link = (unsigned long) &sr->tramp; - regs->nip = sigctx.handler; + if (copy_from_user(current->thread.fpr, &sr->fp_regs, sizeof(sr->fp_regs))) + goto badframe; + + ret = regs->result; - if (get_user(prevsp, &sr->gp_regs[PT_R1]) - || put_user(prevsp, (unsigned int*) regs->gpr[1])) - goto badframe; - } - - PPCDBG(PPCDBG_SIGNAL, "sys32_sigreturn - normal exit returning %ld - pid=%ld current=%lx comm=%s \n", ret, current->pid, current, current->comm); return ret; badframe: - PPCDBG(PPCDBG_SYS32NI, "sys32_sigreturn - badframe - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm); do_exit(SIGSEGV); } /* * Set up a signal frame. */ -static void -setup_frame32(struct pt_regs *regs, struct sigregs32 *frame, +static void setup_frame32(struct pt_regs *regs, struct sigregs32 *frame, unsigned int newsp) { - struct sigcontext32_struct *sc = (struct sigcontext32_struct *)(u64)newsp; + struct sigcontext32_struct *sc = + (struct sigcontext32_struct *)(u64)newsp; + int i; if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) goto badframe; if (regs->msr & MSR_FP) giveup_fpu(current); - /***************************************************************/ - /* */ - /* Copy the register contents for the pt_regs structure on the */ - /* kernel stack to the elf_gregset_t32 structure on the user */ - /* stack. This is a copy of 64 bit register values to 32 bit */ - /* register values. The high order 32 bits of the 64 bit */ - /* registers are not needed since a 32 bit application is */ - /* running and the saved registers are the contents of the */ - /* user registers at the time of a system call. */ - /* */ - /* The values saved on the user stack will be restored into */ - /* the registers during the signal return processing */ - /* */ - /* Note the +1 is needed in order to get the lower 32 bits */ - /* of 64 bit register */ - /***************************************************************/ - if (__copy_to_user(&frame->gp_regs[0], (u32*)(®s->gpr[0])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[1], (u32*)(®s->gpr[1])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[2], (u32*)(®s->gpr[2])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[3], (u32*)(®s->gpr[3])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[4], (u32*)(®s->gpr[4])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[5], (u32*)(®s->gpr[5])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[6], (u32*)(®s->gpr[6])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[7], (u32*)(®s->gpr[7])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[8], (u32*)(®s->gpr[8])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[9], (u32*)(®s->gpr[9])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[10], (u32*)(®s->gpr[10])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[11], (u32*)(®s->gpr[11])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[12], (u32*)(®s->gpr[12])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[13], (u32*)(®s->gpr[13])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[14], (u32*)(®s->gpr[14])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[15], (u32*)(®s->gpr[15])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[16], (u32*)(®s->gpr[16])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[17], (u32*)(®s->gpr[17])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[18], (u32*)(®s->gpr[18])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[19], (u32*)(®s->gpr[19])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[20], (u32*)(®s->gpr[20])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[21], (u32*)(®s->gpr[21])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[22], (u32*)(®s->gpr[22])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[23], (u32*)(®s->gpr[23])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[24], (u32*)(®s->gpr[24])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[25], (u32*)(®s->gpr[25])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[26], (u32*)(®s->gpr[26])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[27], (u32*)(®s->gpr[27])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[28], (u32*)(®s->gpr[28])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[29], (u32*)(®s->gpr[29])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[30], (u32*)(®s->gpr[30])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[31], (u32*)(®s->gpr[31])+1, sizeof(u32))) - goto badframe; + /* + * Copy the register contents for the pt_regs structure on the + * kernel stack to the elf_gregset_t32 structure on the user + * stack. This is a copy of 64 bit register values to 32 bit + * register values. The high order 32 bits of the 64 bit + * registers are not needed since a 32 bit application is + * running and the saved registers are the contents of the + * user registers at the time of a system call. + * + * The values saved on the user stack will be restored into + * the registers during the signal return processing + */ + for (i = 0; i < 32; i++) { + if (__put_user((u32)regs->gpr[i], &frame->gp_regs[i])) + goto badframe; + } - /*****************************************************************************/ - /* Copy the non gpr registers to the user stack */ - /*****************************************************************************/ - - if (__copy_to_user(&frame->gp_regs[PT_NIP], (u32*)(®s->gpr[PT_NIP])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[PT_MSR], (u32*)(®s->gpr[PT_MSR])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[PT_ORIG_R3], (u32*)(®s->gpr[PT_ORIG_R3])+1, - sizeof(u32)) - || __copy_to_user(&frame->gp_regs[PT_CTR], (u32*)(®s->gpr[PT_CTR])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[PT_LNK], (u32*)(®s->gpr[PT_LNK])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[PT_XER], (u32*)(®s->gpr[PT_XER])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[PT_CCR], (u32*)(®s->gpr[PT_CCR])+1, sizeof(u32)) -# if 0 - || __copy_to_user(&frame->gp_regs[PT_MQ], (u32*)(®s->gpr[PT_MQ])+1, sizeof(u32)) + /* + * Copy the non gpr registers to the user stack + */ + if (__put_user((u32)regs->gpr[PT_NIP], &frame->gp_regs[PT_NIP]) + || __put_user((u32)regs->gpr[PT_MSR], &frame->gp_regs[PT_MSR]) + || __put_user((u32)regs->gpr[PT_ORIG_R3], &frame->gp_regs[PT_ORIG_R3]) + || __put_user((u32)regs->gpr[PT_CTR], &frame->gp_regs[PT_CTR]) + || __put_user((u32)regs->gpr[PT_LNK], &frame->gp_regs[PT_LNK]) + || __put_user((u32)regs->gpr[PT_XER], &frame->gp_regs[PT_XER]) + || __put_user((u32)regs->gpr[PT_CCR], &frame->gp_regs[PT_CCR]) +#if 0 + || __put_user((u32)regs->gpr[PT_MQ], &frame->gp_regs[PT_MQ]) #endif - || __copy_to_user(&frame->gp_regs[PT_RESULT], (u32*)(®s->gpr[PT_RESULT])+1, - sizeof(u32))) + || __put_user((u32)regs->gpr[PT_RESULT], &frame->gp_regs[PT_RESULT])) goto badframe; - /*****************************************************************************/ - /* Now copy the floating point registers onto the user stack */ - /* */ - /* Also set up so on the completion of the signal handler, the sys_sigreturn */ - /* will get control to reset the stack */ - /*****************************************************************************/ + /* + * Now copy the floating point registers onto the user stack + * + * Also set up so on the completion of the signal handler, the + * sys_sigreturn will get control to reset the stack + */ if (__copy_to_user(&frame->fp_regs, current->thread.fpr, ELF_NFPREG * sizeof(double)) || __put_user(0x38000000U + __NR_sigreturn, &frame->tramp[0]) /* li r0, __NR_sigreturn */ @@ -487,6 +393,7 @@ flush_icache_range((unsigned long) &frame->tramp[0], (unsigned long) &frame->tramp[2]); + current->thread.fpscr = 0; /* turn off all fp exceptions */ newsp -= __SIGNAL_FRAMESIZE32; if (put_user(regs->gpr[1], (u32*)(u64)newsp) @@ -495,17 +402,17 @@ goto badframe; regs->gpr[1] = newsp & 0xFFFFFFFF; - /**************************************************************/ - /* first parameter to the signal handler is the signal number */ - /* - the value is in gpr3 */ - /* second parameter to the signal handler is the sigcontext */ - /* - set the value into gpr4 */ - /**************************************************************/ + /* + * first parameter to the signal handler is the signal number + * - the value is in gpr3 + * second parameter to the signal handler is the sigcontext + * - set the value into gpr4 + */ regs->gpr[4] = (unsigned long) sc; regs->link = (unsigned long) frame->tramp; return; - badframe: +badframe: udbg_printf("setup_frame32 - badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); PPCDBG_ENTER_DEBUGGER(); #if DEBUG_SIG printk("badframe in setup_frame32, regs=%p frame=%p newsp=%lx\n", @@ -515,31 +422,31 @@ } -/****************************************************************************/ -/* Start of RT signal support */ -/* */ -/* sigset_t is 64 bits for rt signals */ -/* */ -/* System Calls */ -/* sigaction sys32_rt_sigaction */ -/* sigpending sys32_rt_sigpending */ -/* sigprocmask sys32_rt_sigprocmask */ -/* sigreturn sys32_rt_sigreturn */ -/* sigtimedwait sys32_rt_sigtimedwait */ -/* sigqueueinfo sys32_rt_sigqueueinfo */ -/* sigsuspend sys32_rt_sigsuspend */ -/* */ -/* Other routines */ -/* setup_rt_frame32 */ -/* siginfo64to32 */ -/* siginfo32to64 */ -/* */ -/* */ -/****************************************************************************/ +/* + * Start of RT signal support + * + * sigset_t is 64 bits for rt signals + * + * System Calls + * sigaction sys32_rt_sigaction + * sigpending sys32_rt_sigpending + * sigprocmask sys32_rt_sigprocmask + * sigreturn sys32_rt_sigreturn + * sigtimedwait sys32_rt_sigtimedwait + * sigqueueinfo sys32_rt_sigqueueinfo + * sigsuspend sys32_rt_sigsuspend + * + * Other routines + * setup_rt_frame32 + * siginfo64to32 + * siginfo32to64 + */ -// This code executes after the rt signal handler in 32 bit mode has completed and -// returned +/* + * This code executes after the rt signal handler in 32 bit mode has + * completed and returned + */ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, unsigned long r8, struct pt_regs * regs) @@ -547,26 +454,26 @@ struct rt_sigframe_32 *rt_stack_frame; struct sigcontext32_struct sigctx; struct sigregs32 *signalregs; - int ret; elf_gregset_t32 saved_regs; /* an array of 32 bit register values */ sigset_t signal_set; stack_t stack; - unsigned int previous_stack; + int i; ret = 0; /* Adjust the inputted reg1 to point to the first rt signal frame */ rt_stack_frame = (struct rt_sigframe_32 *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32); /* Copy the information from the user stack */ - if (copy_from_user(&sigctx, &rt_stack_frame->uc.uc_mcontext,sizeof(sigctx)) - || copy_from_user(&signal_set, &rt_stack_frame->uc.uc_sigmask,sizeof(signal_set)) - || copy_from_user(&stack,&rt_stack_frame->uc.uc_stack,sizeof(stack))) - { - /* unable to copy from user storage */ + if (copy_from_user(&sigctx, &rt_stack_frame->uc.uc_mcontext, + sizeof(sigctx)) + || copy_from_user(&signal_set, &rt_stack_frame->uc.uc_sigmask, + sizeof(signal_set)) + || copy_from_user(&stack,&rt_stack_frame->uc.uc_stack, + sizeof(stack))) goto badframe; - } - /* Unblock the signal that was processed + /* + * Unblock the signal that was processed * After a signal handler runs - * if the signal is blockable - the signal will be unblocked * ( sigkill and sigstop are not blockable) @@ -578,129 +485,57 @@ recalc_sigpending(); spin_unlock_irq(¤t->sigmask_lock); - /* Set to point to the next rt_sigframe - this is used to determine whether this - * is the last signal to process + /* + * Set to point to the next rt_sigframe - this is used to + * determine whether this is the last signal to process */ - rt_stack_frame ++; - - if (rt_stack_frame == (struct rt_sigframe_32 *)(u64)(sigctx.regs)) - { - signalregs = (struct sigregs32 *) (u64)sigctx.regs; - /* If currently owning the floating point - give them up */ - if (regs->msr & MSR_FP) - { - giveup_fpu(current); - } - if (copy_from_user(saved_regs,&signalregs->gp_regs,sizeof(signalregs->gp_regs))) - { - goto badframe; - } - /**********************************************************************/ - /* The saved reg structure in the frame is an elf_grepset_t32, it is */ - /* a 32 bit register save of the registers in the pt_regs structure */ - /* that was stored on the kernel stack during the system call */ - /* when the system call was interrupted for the signal. Only 32 bits*/ - /* are saved because the sigcontext contains a pointer to the regs */ - /* and the sig context address is passed as a pointer to the signal */ - /* handler. */ - /* */ - /* The entries in the elf_grepset have the same index as the elements */ - /* in the pt_regs structure. */ - /* */ - /**********************************************************************/ - - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - regs->gpr[0] = (u64)(saved_regs[0]) & 0xFFFFFFFF; - regs->gpr[1] = (u64)(saved_regs[1]) & 0xFFFFFFFF; - /**********************************************************************/ - /* Register 2 is the kernel toc - should be reset on any calls into */ - /* the kernel */ - /**********************************************************************/ - regs->gpr[2] = (u64)(saved_regs[2]) & 0xFFFFFFFF; - - regs->gpr[3] = (u64)(saved_regs[3]) & 0xFFFFFFFF; - regs->gpr[4] = (u64)(saved_regs[4]) & 0xFFFFFFFF; - regs->gpr[5] = (u64)(saved_regs[5]) & 0xFFFFFFFF; - regs->gpr[6] = (u64)(saved_regs[6]) & 0xFFFFFFFF; - regs->gpr[7] = (u64)(saved_regs[7]) & 0xFFFFFFFF; - regs->gpr[8] = (u64)(saved_regs[8]) & 0xFFFFFFFF; - regs->gpr[9] = (u64)(saved_regs[9]) & 0xFFFFFFFF; - regs->gpr[10] = (u64)(saved_regs[10]) & 0xFFFFFFFF; - regs->gpr[11] = (u64)(saved_regs[11]) & 0xFFFFFFFF; - regs->gpr[12] = (u64)(saved_regs[12]) & 0xFFFFFFFF; - regs->gpr[13] = (u64)(saved_regs[13]) & 0xFFFFFFFF; - regs->gpr[14] = (u64)(saved_regs[14]) & 0xFFFFFFFF; - regs->gpr[15] = (u64)(saved_regs[15]) & 0xFFFFFFFF; - regs->gpr[16] = (u64)(saved_regs[16]) & 0xFFFFFFFF; - regs->gpr[17] = (u64)(saved_regs[17]) & 0xFFFFFFFF; - regs->gpr[18] = (u64)(saved_regs[18]) & 0xFFFFFFFF; - regs->gpr[19] = (u64)(saved_regs[19]) & 0xFFFFFFFF; - regs->gpr[20] = (u64)(saved_regs[20]) & 0xFFFFFFFF; - regs->gpr[21] = (u64)(saved_regs[21]) & 0xFFFFFFFF; - regs->gpr[22] = (u64)(saved_regs[22]) & 0xFFFFFFFF; - regs->gpr[23] = (u64)(saved_regs[23]) & 0xFFFFFFFF; - regs->gpr[24] = (u64)(saved_regs[24]) & 0xFFFFFFFF; - regs->gpr[25] = (u64)(saved_regs[25]) & 0xFFFFFFFF; - regs->gpr[26] = (u64)(saved_regs[26]) & 0xFFFFFFFF; - regs->gpr[27] = (u64)(saved_regs[27]) & 0xFFFFFFFF; - regs->gpr[28] = (u64)(saved_regs[28]) & 0xFFFFFFFF; - regs->gpr[29] = (u64)(saved_regs[29]) & 0xFFFFFFFF; - regs->gpr[30] = (u64)(saved_regs[30]) & 0xFFFFFFFF; - regs->gpr[31] = (u64)(saved_regs[31]) & 0xFFFFFFFF; - /****************************************************/ - /* restore the non gpr registers */ - /****************************************************/ - regs->msr = (u64)(saved_regs[PT_MSR]) & 0xFFFFFFFF; - - regs->nip = (u64)(saved_regs[PT_NIP]) & 0xFFFFFFFF; - regs->orig_gpr3 = (u64)(saved_regs[PT_ORIG_R3]) & 0xFFFFFFFF; - regs->ctr = (u64)(saved_regs[PT_CTR]) & 0xFFFFFFFF; - regs->link = (u64)(saved_regs[PT_LNK]) & 0xFFFFFFFF; - regs->xer = (u64)(saved_regs[PT_XER]) & 0xFFFFFFFF; - regs->ccr = (u64)(saved_regs[PT_CCR]) & 0xFFFFFFFF; - /* regs->softe is left unchanged (like MSR.EE) */ - /******************************************************/ - /* the DAR and the DSISR are only relevant during a */ - /* data or instruction storage interrupt. The value */ - /* will be set to zero. */ - /******************************************************/ - regs->dar = 0; - regs->dsisr = 0; - regs->result = (u64)(saved_regs[PT_RESULT]) & 0xFFFFFFFF; - ret = regs->result; - } - else /* more signals to go */ - { - udbg_printf("hey should not occur\n"); - regs->gpr[1] = (u64)rt_stack_frame - __SIGNAL_FRAMESIZE32; - if (copy_from_user(&sigctx, &rt_stack_frame->uc.uc_mcontext,sizeof(sigctx))) - { - goto badframe; - } - signalregs = (struct sigregs32 *) (u64)sigctx.regs; - /* first parm to signal handler is the signal number */ - regs->gpr[3] = ret = sigctx.signal; - /* second parm is a pointer to sig info */ - get_user(regs->gpr[4], &rt_stack_frame->pinfo); - /* third parm is a pointer to the ucontext */ - get_user(regs->gpr[5], &rt_stack_frame->puc); - /* fourth parm is the stack frame */ - regs->gpr[6] = (u64)rt_stack_frame; - /* Set up link register to return to sigreturn when the */ - /* signal handler completes */ - regs->link = (u64)&signalregs->tramp; - /* Set next instruction to the start fo the signal handler */ - regs->nip = sigctx.handler; - /* Set the reg1 to look like a call to the signal handler */ - if (get_user(previous_stack,&signalregs->gp_regs[PT_R1]) - || put_user(previous_stack, (unsigned long *)regs->gpr[1])) - { - goto badframe; - } - - } - + signalregs = (struct sigregs32 *) (u64)sigctx.regs; + /* If currently owning the floating point - give them up */ + if (regs->msr & MSR_FP) + giveup_fpu(current); + if (copy_from_user(saved_regs, &signalregs->gp_regs, + sizeof(signalregs->gp_regs))) + goto badframe; + /* + * The saved reg structure in the frame is an elf_grepset_t32, + * it is a 32 bit register save of the registers in the + * pt_regs structure that was stored on the kernel stack + * during the system call when the system call was interrupted + * for the signal. Only 32 bits are saved because the + * sigcontext contains a pointer to the regs and the sig + * context address is passed as a pointer to the signal handler + * + * The entries in the elf_grepset have the same index as + * the elements in the pt_regs structure. + */ + saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) + | (saved_regs[PT_MSR] & MSR_USERCHANGE); + /* + * Register 2 is the kernel toc - should be reset on any + * calls into the kernel + */ + for (i = 0; i < 32; i++) + regs->gpr[i] = (u64)(saved_regs[i]) & 0xFFFFFFFF; + /* + * restore the non gpr registers + */ + regs->msr = (u64)(saved_regs[PT_MSR]) & 0xFFFFFFFF; + regs->nip = (u64)(saved_regs[PT_NIP]) & 0xFFFFFFFF; + regs->orig_gpr3 = (u64)(saved_regs[PT_ORIG_R3]) & 0xFFFFFFFF; + regs->ctr = (u64)(saved_regs[PT_CTR]) & 0xFFFFFFFF; + regs->link = (u64)(saved_regs[PT_LNK]) & 0xFFFFFFFF; + regs->xer = (u64)(saved_regs[PT_XER]) & 0xFFFFFFFF; + regs->ccr = (u64)(saved_regs[PT_CCR]) & 0xFFFFFFFF; + /* regs->softe is left unchanged (like MSR.EE) */ + /* + * the DAR and the DSISR are only relevant during a + * data or instruction storage interrupt. The value + * will be set to zero. + */ + regs->dar = 0; + regs->dsisr = 0; + regs->result = (u64)(saved_regs[PT_RESULT]) & 0xFFFFFFFF; + ret = regs->result; return ret; badframe: @@ -709,14 +544,13 @@ -asmlinkage long sys32_rt_sigaction(int sig, const struct sigaction32 *act, struct sigaction32 *oact, size_t sigsetsize) +asmlinkage long sys32_rt_sigaction(int sig, const struct sigaction32 *act, + struct sigaction32 *oact, size_t sigsetsize) { struct k_sigaction new_ka, old_ka; int ret; sigset32_t set32; - PPCDBG(PPCDBG_SIGNAL, "sys32_rt_sigaction - entered - sig=%x \n", sig); - /* XXX: Don't preclude handling different sized sigset_t's. */ if (sigsetsize != sizeof(sigset32_t)) return -EINVAL; @@ -735,15 +569,12 @@ case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32); } - ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); - if (ret) return -EFAULT; } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - if (!ret && oact) { switch (_NSIG_WORDS) { case 4: @@ -764,30 +595,28 @@ sizeof(sigset32_t)); ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); } - - - PPCDBG(PPCDBG_SIGNAL, "sys32_rt_sigaction - exiting - sig=%x \n", sig); return ret; } -extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, - size_t sigsetsize); +extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, + sigset_t *oset, size_t sigsetsize); -/* Note: it is necessary to treat how as an unsigned int, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. +/* + * Note: it is necessary to treat how as an unsigned int, with the + * corresponding cast to a signed int to insure that the proper + * conversion (sign extension) between the register representation + * of a signed int (msr in 32-bit mode) and the register representation + * of a signed int (msr in 64-bit mode) is performed. */ -asmlinkage long sys32_rt_sigprocmask(u32 how, sigset32_t *set, sigset32_t *oset, size_t sigsetsize) +asmlinkage long sys32_rt_sigprocmask(u32 how, sigset32_t *set, + sigset32_t *oset, size_t sigsetsize) { sigset_t s; sigset32_t s32; int ret; mm_segment_t old_fs = get_fs(); - PPCDBG(PPCDBG_SIGNAL, "sys32_rt_sigprocmask - entered how=%x \n", (int)how); - if (set) { if (copy_from_user (&s32, set, sizeof(sigset32_t))) return -EFAULT; @@ -800,11 +629,12 @@ } } - set_fs (KERNEL_DS); + set_fs(KERNEL_DS); ret = sys_rt_sigprocmask((int)how, set ? &s : NULL, oset ? &s : NULL, sigsetsize); - set_fs (old_fs); - if (ret) return ret; + set_fs(old_fs); + if (ret) + return ret; if (oset) { switch (_NSIG_WORDS) { case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; @@ -822,18 +652,17 @@ extern asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize); - -asmlinkage long sys32_rt_sigpending(sigset32_t *set, __kernel_size_t32 sigsetsize) +asmlinkage long sys32_rt_sigpending(sigset32_t *set, + __kernel_size_t32 sigsetsize) { - sigset_t s; sigset32_t s32; int ret; mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); + + set_fs(KERNEL_DS); ret = sys_rt_sigpending(&s, sigsetsize); - set_fs (old_fs); + set_fs(old_fs); if (!ret) { switch (_NSIG_WORDS) { case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; @@ -848,52 +677,51 @@ } - -siginfo_t32 * -siginfo64to32(siginfo_t32 *d, siginfo_t *s) +siginfo_t32 *siginfo64to32(siginfo_t32 *d, siginfo_t *s) { memset (d, 0, sizeof(siginfo_t32)); d->si_signo = s->si_signo; d->si_errno = s->si_errno; - d->si_code = s->si_code; + /* XXX why dont we just implement copy_siginfo_to_user32? - Anton */ + d->si_code = s->si_code & 0xffff; if (s->si_signo >= SIGRTMIN) { d->si_pid = s->si_pid; d->si_uid = s->si_uid; - d->si_int = s->si_int; - } else switch (s->si_signo) { - /* XXX: What about POSIX1.b timers */ - case SIGCHLD: - d->si_pid = s->si_pid; - d->si_status = s->si_status; - d->si_utime = s->si_utime; - d->si_stime = s->si_stime; - break; - case SIGSEGV: - case SIGBUS: - case SIGFPE: - case SIGILL: - d->si_addr = (long)(s->si_addr); - break; - case SIGPOLL: - d->si_band = s->si_band; - d->si_fd = s->si_fd; - break; - default: - d->si_pid = s->si_pid; - d->si_uid = s->si_uid; - break; + } else { + switch (s->si_signo) { + /* XXX: What about POSIX1.b timers */ + case SIGCHLD: + d->si_pid = s->si_pid; + d->si_status = s->si_status; + d->si_utime = s->si_utime; + d->si_stime = s->si_stime; + break; + case SIGSEGV: + case SIGBUS: + case SIGFPE: + case SIGILL: + d->si_addr = (long)(s->si_addr); + break; + case SIGPOLL: + d->si_band = s->si_band; + d->si_fd = s->si_fd; + break; + default: + d->si_pid = s->si_pid; + d->si_uid = s->si_uid; + break; + } } return d; } -extern asmlinkage long -sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo, - const struct timespec *uts, size_t sigsetsize); - -asmlinkage long -sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo, - struct timespec32 *uts, __kernel_size_t32 sigsetsize) +extern asmlinkage long sys_rt_sigtimedwait(const sigset_t *uthese, + siginfo_t *uinfo, const struct timespec *uts, + size_t sigsetsize); + +asmlinkage long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo, + struct timespec32 *uts, __kernel_size_t32 sigsetsize) { sigset_t s; sigset32_t s32; @@ -903,7 +731,7 @@ siginfo_t info; siginfo_t32 info32; - if (copy_from_user (&s32, uthese, sizeof(sigset32_t))) + if (copy_from_user(&s32, uthese, sizeof(sigset32_t))) return -EFAULT; switch (_NSIG_WORDS) { case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); @@ -912,20 +740,18 @@ case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); } if (uts) { - ret = get_user (t.tv_sec, &uts->tv_sec); - ret |= __get_user (t.tv_nsec, &uts->tv_nsec); + ret = get_user(t.tv_sec, &uts->tv_sec); + ret |= __get_user(t.tv_nsec, &uts->tv_nsec); if (ret) return -EFAULT; } - set_fs (KERNEL_DS); + set_fs(KERNEL_DS); if (uts) - { ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize); - } else { - ret = sys_rt_sigtimedwait(&s, &info, (struct timespec *)uts, sigsetsize); - } - - set_fs (old_fs); + else + ret = sys_rt_sigtimedwait(&s, &info, (struct timespec *)uts, + sigsetsize); + set_fs(old_fs); if (ret >= 0 && uinfo) { if (copy_to_user (uinfo, siginfo64to32(&info32, &info), sizeof(siginfo_t32))) @@ -936,8 +762,7 @@ -siginfo_t * -siginfo32to64(siginfo_t *d, siginfo_t32 *s) +siginfo_t * siginfo32to64(siginfo_t *d, siginfo_t32 *s) { d->si_signo = s->si_signo; d->si_errno = s->si_errno; @@ -946,29 +771,30 @@ d->si_pid = s->si_pid; d->si_uid = s->si_uid; d->si_int = s->si_int; - - } else switch (s->si_signo) { - /* XXX: What about POSIX1.b timers */ - case SIGCHLD: - d->si_pid = s->si_pid; - d->si_status = s->si_status; - d->si_utime = s->si_utime; - d->si_stime = s->si_stime; - break; - case SIGSEGV: - case SIGBUS: - case SIGFPE: - case SIGILL: - d->si_addr = (void *)A(s->si_addr); - break; - case SIGPOLL: - d->si_band = s->si_band; - d->si_fd = s->si_fd; - break; - default: - d->si_pid = s->si_pid; - d->si_uid = s->si_uid; - break; + } else { + switch (s->si_signo) { + /* XXX: What about POSIX1.b timers */ + case SIGCHLD: + d->si_pid = s->si_pid; + d->si_status = s->si_status; + d->si_utime = s->si_utime; + d->si_stime = s->si_stime; + break; + case SIGSEGV: + case SIGBUS: + case SIGFPE: + case SIGILL: + d->si_addr = (void *)A(s->si_addr); + break; + case SIGPOLL: + d->si_band = s->si_band; + d->si_fd = s->si_fd; + break; + default: + d->si_pid = s->si_pid; + d->si_uid = s->si_uid; + break; + } } return d; } @@ -976,10 +802,12 @@ extern asmlinkage long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo); -/* Note: it is necessary to treat pid and sig as unsigned ints, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. +/* + * Note: it is necessary to treat pid and sig as unsigned ints, with the + * corresponding cast to a signed int to insure that the proper conversion + * (sign extension) between the register representation of a signed int + * (msr in 32-bit mode) and the register representation of a signed int + * (msr in 64-bit mode) is performed. */ asmlinkage long sys32_rt_sigqueueinfo(u32 pid, u32 sig, siginfo_t32 *uinfo) { @@ -1000,11 +828,12 @@ } -int do_signal(sigset_t *oldset, struct pt_regs *regs); -int sys32_rt_sigsuspend(sigset32_t* unewset, size_t sigsetsize, int p3, int p4, int p6, int p7, struct pt_regs *regs) +extern int do_signal(sigset_t *oldset, struct pt_regs *regs); + +int sys32_rt_sigsuspend(sigset32_t* unewset, size_t sigsetsize, int p3, + int p4, int p6, int p7, struct pt_regs *regs) { sigset_t saveset, newset; - sigset32_t s32; /* XXX: Don't preclude handling different sized sigset_t's. */ @@ -1014,13 +843,15 @@ if (copy_from_user(&s32, unewset, sizeof(s32))) return -EFAULT; - /* Swap the 2 words of the 64-bit sigset_t (they are stored in the "wrong" endian in 32-bit user storage). */ - switch (_NSIG_WORDS) - { - case 4: newset.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); - case 3: newset.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); - case 2: newset.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); - case 1: newset.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); + /* + * Swap the 2 words of the 64-bit sigset_t (they are stored + * in the "wrong" endian in 32-bit user storage). + */ + switch (_NSIG_WORDS) { + case 4: newset.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); + case 3: newset.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); + case 2: newset.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); + case 1: newset.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); } sigdelsetmask(&newset, ~_BLOCKABLE); @@ -1041,102 +872,58 @@ } - - - - - - /* * Set up a rt signal frame. */ -static void -setup_rt_frame32(struct pt_regs *regs, struct sigregs32 *frame, +static void setup_rt_frame32(struct pt_regs *regs, struct sigregs32 *frame, unsigned int newsp) { - unsigned int copyreg4,copyreg5; + unsigned int copyreg4, copyreg5; struct rt_sigframe_32 * rt_sf = (struct rt_sigframe_32 *) (u64)newsp; - + int i; if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) goto badframe; if (regs->msr & MSR_FP) giveup_fpu(current); - /***************************************************************/ - /* */ - /* Copy the register contents for the pt_regs structure on the */ - /* kernel stack to the elf_gregset_t32 structure on the user */ - /* stack. This is a copy of 64 bit register values to 32 bit */ - /* register values. The high order 32 bits of the 64 bit */ - /* registers are not needed since a 32 bit application is */ - /* running and the saved registers are the contents of the */ - /* user registers at the time of a system call. */ - /* */ - /* The values saved on the user stack will be restored into */ - /* the registers during the signal return processing */ - /* */ - /* Note the +1 is needed in order to get the lower 32 bits */ - /* of 64 bit register */ - /***************************************************************/ - if (__copy_to_user(&frame->gp_regs[0], (u32*)(®s->gpr[0])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[1], (u32*)(®s->gpr[1])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[2], (u32*)(®s->gpr[2])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[3], (u32*)(®s->gpr[3])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[4], (u32*)(®s->gpr[4])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[5], (u32*)(®s->gpr[5])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[6], (u32*)(®s->gpr[6])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[7], (u32*)(®s->gpr[7])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[8], (u32*)(®s->gpr[8])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[9], (u32*)(®s->gpr[9])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[10], (u32*)(®s->gpr[10])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[11], (u32*)(®s->gpr[11])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[12], (u32*)(®s->gpr[12])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[13], (u32*)(®s->gpr[13])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[14], (u32*)(®s->gpr[14])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[15], (u32*)(®s->gpr[15])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[16], (u32*)(®s->gpr[16])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[17], (u32*)(®s->gpr[17])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[18], (u32*)(®s->gpr[18])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[19], (u32*)(®s->gpr[19])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[20], (u32*)(®s->gpr[20])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[21], (u32*)(®s->gpr[21])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[22], (u32*)(®s->gpr[22])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[23], (u32*)(®s->gpr[23])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[24], (u32*)(®s->gpr[24])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[25], (u32*)(®s->gpr[25])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[26], (u32*)(®s->gpr[26])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[27], (u32*)(®s->gpr[27])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[28], (u32*)(®s->gpr[28])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[29], (u32*)(®s->gpr[29])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[30], (u32*)(®s->gpr[30])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[31], (u32*)(®s->gpr[31])+1, sizeof(u32))) - goto badframe; - - /*****************************************************************************/ - /* Copy the non gpr registers to the user stack */ - /*****************************************************************************/ - - if (__copy_to_user(&frame->gp_regs[PT_NIP], (u32*)(®s->gpr[PT_NIP])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[PT_MSR], (u32*)(®s->gpr[PT_MSR])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[PT_ORIG_R3], (u32*)(®s->gpr[PT_ORIG_R3])+1, - sizeof(u32)) - || __copy_to_user(&frame->gp_regs[PT_CTR], (u32*)(®s->gpr[PT_CTR])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[PT_LNK], (u32*)(®s->gpr[PT_LNK])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[PT_XER], (u32*)(®s->gpr[PT_XER])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[PT_CCR], (u32*)(®s->gpr[PT_CCR])+1, sizeof(u32)) - || __copy_to_user(&frame->gp_regs[PT_RESULT], (u32*)(®s->gpr[PT_RESULT])+1, - sizeof(u32))) - goto badframe; + /* + * Copy the register contents for the pt_regs structure on the + * kernel stack to the elf_gregset_t32 structure on the user + * stack. This is a copy of 64 bit register values to 32 bit + * register values. The high order 32 bits of the 64 bit + * registers are not needed since a 32 bit application is + * running and the saved registers are the contents of the + * user registers at the time of a system call. + * + * The values saved on the user stack will be restored into + * the registers during the signal return processing + */ + for (i = 0; i < 32; i++) { + if (__put_user((u32)regs->gpr[i], &frame->gp_regs[i])) + goto badframe; + } - /*****************************************************************************/ - /* Now copy the floating point registers onto the user stack */ - /* */ - /* Also set up so on the completion of the signal handler, the sys_sigreturn */ - /* will get control to reset the stack */ - /*****************************************************************************/ + /* + * Copy the non gpr registers to the user stack + */ + if (__put_user((u32)regs->gpr[PT_NIP], &frame->gp_regs[PT_NIP]) + || __put_user((u32)regs->gpr[PT_MSR], &frame->gp_regs[PT_MSR]) + || __put_user((u32)regs->gpr[PT_ORIG_R3], &frame->gp_regs[PT_ORIG_R3]) + || __put_user((u32)regs->gpr[PT_CTR], &frame->gp_regs[PT_CTR]) + || __put_user((u32)regs->gpr[PT_LNK], &frame->gp_regs[PT_LNK]) + || __put_user((u32)regs->gpr[PT_XER], &frame->gp_regs[PT_XER]) + || __put_user((u32)regs->gpr[PT_CCR], &frame->gp_regs[PT_CCR]) + || __put_user((u32)regs->gpr[PT_RESULT], &frame->gp_regs[PT_RESULT])) + goto badframe; + /* + * Now copy the floating point registers onto the user stack + * + * Also set up so on the completion of the signal handler, the + * sys_sigreturn will get control to reset the stack + */ if (__copy_to_user(&frame->fp_regs, current->thread.fpr, ELF_NFPREG * sizeof(double)) || __put_user(0x38000000U + __NR_rt_sigreturn, &frame->tramp[0]) /* li r0, __NR_rt_sigreturn */ @@ -1145,11 +932,12 @@ flush_icache_range((unsigned long) &frame->tramp[0], (unsigned long) &frame->tramp[2]); + current->thread.fpscr = 0; /* turn off all fp exceptions */ - - /* Retrieve rt_sigframe from stack and - set up registers for signal handler - */ + /* + * Retrieve rt_sigframe from stack and + * set up registers for signal handler + */ newsp -= __SIGNAL_FRAMESIZE32; @@ -1162,18 +950,13 @@ regs->gpr[4] = copyreg4; regs->gpr[5] = copyreg5; - - regs->gpr[1] = newsp; regs->gpr[6] = (unsigned long) rt_sf; - - regs->link = (unsigned long) frame->tramp; return; - - badframe: +badframe: udbg_printf("setup_frame32 - badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); PPCDBG_ENTER_DEBUGGER(); #if DEBUG_SIG printk("badframe in setup_frame32, regs=%p frame=%p newsp=%lx\n", @@ -1186,9 +969,9 @@ /* * OK, we're invoking a handler */ -static void -handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs, unsigned int *newspp, unsigned int frame) +static void handle_signal32(unsigned long sig, siginfo_t *info, + sigset_t *oldset, struct pt_regs * regs, unsigned int *newspp, + unsigned int frame) { struct sigcontext32_struct *sc; struct rt_sigframe_32 *rt_stack_frame; @@ -1201,46 +984,52 @@ !(ka->sa.sa_flags & SA_RESTART)))) regs->result = -EINTR; - /* Set up the signal frame */ - /* Determine if an real time frame - siginfo required */ - if (ka->sa.sa_flags & SA_SIGINFO) - { + /* + * Set up the signal frame + * Determine if an real time frame - siginfo required + */ + if (ka->sa.sa_flags & SA_SIGINFO) { siginfo64to32(&siginfo32bit,info); *newspp -= sizeof(*rt_stack_frame); - rt_stack_frame = (struct rt_sigframe_32 *) (u64)(*newspp) ; - - if (verify_area(VERIFY_WRITE, rt_stack_frame, sizeof(*rt_stack_frame))) - { + rt_stack_frame = (struct rt_sigframe_32 *)(u64)(*newspp); + + if (verify_area(VERIFY_WRITE, rt_stack_frame, + sizeof(*rt_stack_frame))) goto badframe; - } - if (__put_user((u32)(u64)ka->sa.sa_handler, &rt_stack_frame->uc.uc_mcontext.handler) - || __put_user((u32)(u64)&rt_stack_frame->info, &rt_stack_frame->pinfo) - || __put_user((u32)(u64)&rt_stack_frame->uc, &rt_stack_frame->puc) + if (__put_user((u32)(u64)ka->sa.sa_handler, + &rt_stack_frame->uc.uc_mcontext.handler) + || __put_user((u32)(u64)&rt_stack_frame->info, + &rt_stack_frame->pinfo) + || __put_user((u32)(u64)&rt_stack_frame->uc, + &rt_stack_frame->puc) /* put the siginfo on the user stack */ - || __copy_to_user(&rt_stack_frame->info,&siginfo32bit,sizeof(siginfo32bit)) + || __copy_to_user(&rt_stack_frame->info, &siginfo32bit, + sizeof(siginfo32bit)) /* set the ucontext on the user stack */ - || __put_user(0,&rt_stack_frame->uc.uc_flags) - || __put_user(0,&rt_stack_frame->uc.uc_link) - || __put_user(current->sas_ss_sp, &rt_stack_frame->uc.uc_stack.ss_sp) + || __put_user(0, &rt_stack_frame->uc.uc_flags) + || __put_user(0, &rt_stack_frame->uc.uc_link) + || __put_user(current->sas_ss_sp, + &rt_stack_frame->uc.uc_stack.ss_sp) || __put_user(sas_ss_flags(regs->gpr[1]), - &rt_stack_frame->uc.uc_stack.ss_flags) - || __put_user(current->sas_ss_size, &rt_stack_frame->uc.uc_stack.ss_size) - || __copy_to_user(&rt_stack_frame->uc.uc_sigmask, oldset,sizeof(*oldset)) + &rt_stack_frame->uc.uc_stack.ss_flags) + || __put_user(current->sas_ss_size, + &rt_stack_frame->uc.uc_stack.ss_size) + || __copy_to_user(&rt_stack_frame->uc.uc_sigmask, + oldset, sizeof(*oldset)) /* point the mcontext.regs to the pramble register frame */ || __put_user(frame, &rt_stack_frame->uc.uc_mcontext.regs) || __put_user(sig,&rt_stack_frame->uc.uc_mcontext.signal)) - { goto badframe; - } } else { /* Put another sigcontext on the stack */ *newspp -= sizeof(*sc); sc = (struct sigcontext32_struct *)(u64)*newspp; if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) goto badframe; - - /* Note the upper 32 bits of the signal mask are stored in the */ - /* unused part of the signal stack frame */ + /* + * Note the upper 32 bits of the signal mask are stored + * in the unused part of the signal stack frame + */ if (__put_user((u32)(u64)ka->sa.sa_handler, &sc->handler) || __put_user(oldset->sig[0], &sc->oldmask) || __put_user((oldset->sig[0] >> 32), &sc->_unused[3]) @@ -1272,59 +1061,64 @@ } -/****************************************************************************/ -/* Start Alternate signal stack support */ -/* */ -/* */ -/* */ -/* System Calls */ -/* sigaltatck sys32_sigaltstack */ -/* */ -/****************************************************************************/ - +/* + * Start Alternate signal stack support + * + * System Calls + * sigaltatck sys32_sigaltstack + */ -asmlinkage int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3, int p4, int p6, - int p7, struct pt_regs *regs) +asmlinkage int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3, + int p4, int p6, int p7, struct pt_regs *regs) { stack_t uss, uoss; int ret; mm_segment_t old_fs; unsigned long sp; - /* set sp to the user stack on entry to the system call */ - /* the system call router sets R9 to the saved registers */ + /* + * set sp to the user stack on entry to the system call + * the system call router sets R9 to the saved registers + */ sp = regs->gpr[1]; - /* Put new stack info in local 64 bit stack struct */ - if (newstack && (get_user((long)uss.ss_sp, &((stack_32_t *)(long)newstack)->ss_sp) || - __get_user(uss.ss_flags, &((stack_32_t *)(long)newstack)->ss_flags) || - __get_user(uss.ss_size, &((stack_32_t *)(long)newstack)->ss_size))) + /* Put new stack info in local 64 bit stack struct */ + if (newstack && + (get_user((long)uss.ss_sp, + &((stack_32_t *)(long)newstack)->ss_sp) || + __get_user(uss.ss_flags, + &((stack_32_t *)(long)newstack)->ss_flags) || + __get_user(uss.ss_size, + &((stack_32_t *)(long)newstack)->ss_size))) return -EFAULT; - old_fs = get_fs(); set_fs(KERNEL_DS); - ret = do_sigaltstack(newstack ? &uss : NULL, oldstack ? &uoss : NULL, sp); + ret = do_sigaltstack(newstack ? &uss : NULL, oldstack ? &uoss : NULL, + sp); set_fs(old_fs); - /* Copy the stack information to the user output buffer */ - if (!ret && oldstack && (put_user((long)uoss.ss_sp, &((stack_32_t *)(long)oldstack)->ss_sp) || - __put_user(uoss.ss_flags, &((stack_32_t *)(long)oldstack)->ss_flags) || - __put_user(uoss.ss_size, &((stack_32_t *)(long)oldstack)->ss_size))) + /* Copy the stack information to the user output buffer */ + if (!ret && oldstack && + (put_user((long)uoss.ss_sp, + &((stack_32_t *)(long)oldstack)->ss_sp) || + __put_user(uoss.ss_flags, + &((stack_32_t *)(long)oldstack)->ss_flags) || + __put_user(uoss.ss_size, + &((stack_32_t *)(long)oldstack)->ss_size))) return -EFAULT; return ret; } -/****************************************************************************/ -/* Start of do_signal32 routine */ -/* */ -/* This routine gets control when a pemding signal needs to be processed */ -/* in the 32 bit target thread - */ -/* */ -/* It handles both rt and non-rt signals */ -/* */ -/****************************************************************************/ +/* + * Start of do_signal32 routine + * + * This routine gets control when a pemding signal needs to be processed + * in the 32 bit target thread - + * + * It handles both rt and non-rt signals + */ /* * Note that 'init' is a special process: it doesn't get signals it doesn't @@ -1348,20 +1142,12 @@ if (signr > 0) { ka = ¤t->sig->action[signr-1]; - PPCDBG(PPCDBG_SIGNAL, " do signal :sigaction flags = %lx \n" ,ka->sa.sa_flags); - PPCDBG(PPCDBG_SIGNAL, " do signal :on sig stack = %lx \n" ,on_sig_stack(regs->gpr[1])); - PPCDBG(PPCDBG_SIGNAL, " do signal :reg1 = %lx \n" ,regs->gpr[1]); - PPCDBG(PPCDBG_SIGNAL, " do signal :alt stack = %lx \n" ,current->sas_ss_sp); - PPCDBG(PPCDBG_SIGNAL, " do signal :alt stack size = %lx \n" ,current->sas_ss_size); - - if ( (ka->sa.sa_flags & SA_ONSTACK) - && (! on_sig_stack(regs->gpr[1]))) - { + if ((ka->sa.sa_flags & SA_ONSTACK) && + (!on_sig_stack(regs->gpr[1]))) newsp = (current->sas_ss_sp + current->sas_ss_size); - } else + else newsp = regs->gpr[1]; newsp = frame = newsp - sizeof(struct sigregs32); - /* Whee! Actually deliver the signal. */ handle_signal32(signr, &info, oldset, regs, &newsp, frame); } @@ -1378,12 +1164,11 @@ if (newsp == frame) return 0; /* no signals delivered */ - // Invoke correct stack setup routine + /* Invoke correct stack setup routine */ if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame32(regs, (struct sigregs32*)(u64)frame, newsp); else setup_frame32(regs, (struct sigregs32*)(u64)frame, newsp); return 1; - } diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c --- a/arch/ppc64/kernel/smp.c Sun Jun 2 18:44:58 2002 +++ b/arch/ppc64/kernel/smp.c Sun Jun 2 18:44:58 2002 @@ -31,6 +31,7 @@ /* #include */ #include #include +#include #include #include @@ -58,7 +59,6 @@ int smp_num_cpus = 1; int smp_tb_synchronized = 0; spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED; -cycles_t cacheflush_time; unsigned long cache_decay_ticks; static int max_cpus __initdata = NR_CPUS; @@ -595,12 +595,13 @@ } /* - * XXX very rough, assumes 20 bus cycles to read a cache line, - * timebase increments every 4 bus cycles, 32kB L1 data cache. + * XXX very rough. On POWER4 we optimise tlb flushes for + * tasks that only run on one cpu so we increase decay ticks. */ - cacheflush_time = 5 * 1024; - /* XXX - Fix - Anton */ - cache_decay_ticks = 0; + if (__is_processor(PV_POWER4)) + cache_decay_ticks = HZ/50; + else + cache_decay_ticks = HZ/100; /* Probe arch for CPUs */ cpu_nr = ppc_md.smp_probe(); diff -Nru a/arch/ppc64/kernel/stab.c b/arch/ppc64/kernel/stab.c --- a/arch/ppc64/kernel/stab.c Sun Jun 2 18:44:58 2002 +++ b/arch/ppc64/kernel/stab.c Sun Jun 2 18:44:58 2002 @@ -3,6 +3,8 @@ * * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com * Copyright (c) 2001 Dave Engebretsen + * + * Copyright (C) 2002 Anton Blanchard , IBM * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -10,6 +12,8 @@ * 2 of the License, or (at your option) any later version. */ +/* XXX Note: Changes for bolted region have not been merged - Anton */ + #include #include #include @@ -18,11 +22,10 @@ #include #include -int make_ste(unsigned long stab, - unsigned long esid, unsigned long vsid); -void make_slbe(unsigned long esid, unsigned long vsid, - int large); -extern struct Naca *naca; +int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid); +void make_slbe(unsigned long esid, unsigned long vsid, int large); + +#define cpu_has_slb() (__is_processor(PV_POWER4)) /* * Build an entry for the base kernel segment and put it into @@ -36,26 +39,28 @@ esid = GET_ESID(KERNELBASE); vsid = get_kernel_vsid(esid << SID_SHIFT); - if (!__is_processor(PV_POWER4)) { - __asm__ __volatile__("isync; slbia; isync":::"memory"); - make_ste(stab, esid, vsid); - } else { - /* Invalidate the entire SLB & all the ERATS */ - __asm__ __volatile__("isync" : : : "memory"); -#ifndef CONFIG_PPC_ISERIES - __asm__ __volatile__("slbmte %0,%0" - : : "r" (0) : "memory"); - __asm__ __volatile__("isync; slbia; isync":::"memory"); - make_slbe(esid, vsid, 0); + if (cpu_has_slb()) { + /* Invalidate the entire SLB & all the ERATS */ +#ifdef CONFIG_PPC_ISERIES + asm volatile("isync; slbia; isync":::"memory"); #else - __asm__ __volatile__("isync; slbia; isync":::"memory"); + asm volatile("isync":::"memory"); + asm volatile("slbmte %0,%0"::"r" (0) : "memory"); + asm volatile("isync; slbia; isync":::"memory"); + make_slbe(esid, vsid, 0); #endif - } + } else { + asm volatile("isync; slbia; isync":::"memory"); + make_ste(stab, esid, vsid); + + /* Order update */ + asm volatile("sync":::"memory"); + } } /* * Create a segment table entry for the given esid/vsid pair. - */ + */ int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) { unsigned long entry, group, old_esid, castout_entry, i; @@ -66,21 +71,15 @@ global_entry = (esid & 0x1f) << 3; ste = (STE *)(stab | ((esid & 0x1f) << 7)); - /* - * Find an empty entry, if one exists. - */ - for(group = 0; group < 2; group++) { - for(entry = 0; entry < 8; entry++, ste++) { - if(!(ste->dw0.dw0.v)) { + /* Find an empty entry, if one exists. */ + for (group = 0; group < 2; group++) { + for (entry = 0; entry < 8; entry++, ste++) { + if (!(ste->dw0.dw0.v)) { ste->dw1.dw1.vsid = vsid; - /* Order VSID updte */ - __asm__ __volatile__ ("eieio" : : : "memory"); ste->dw0.dw0.esid = esid; - ste->dw0.dw0.v = 1; ste->dw0.dw0.kp = 1; - /* Order update */ - __asm__ __volatile__ ("sync" : : : "memory"); - + asm volatile("eieio":::"memory"); + ste->dw0.dw0.v = 1; return(global_entry | entry); } } @@ -100,8 +99,8 @@ PMC_SW_PROCESSOR(stab_capacity_castouts); castout_entry = get_paca()->xStab_data.next_round_robin; - for(i = 0; i < 16; i++) { - if(castout_entry < 8) { + for (i = 0; i < 16; i++) { + if (castout_entry < 8) { global_entry = (esid & 0x1f) << 3; ste = (STE *)(stab | ((esid & 0x1f) << 7)); castout_ste = ste + castout_entry; @@ -111,12 +110,9 @@ castout_ste = ste + (castout_entry - 8); } - if((((castout_ste->dw0.dw0.esid) >> 32) == 0) || - (((castout_ste->dw0.dw0.esid) & 0xffffffff) > 0)) { - /* Found an entry to castout. It is either a user */ - /* region, or a secondary kernel segment. */ + /* Dont cast out the first kernel segment */ + if (castout_ste->dw0.dw0.esid != GET_ESID(KERNELBASE)) break; - } castout_entry = (castout_entry + 1) & 0xf; } @@ -126,21 +122,21 @@ /* Modify the old entry to the new value. */ /* Force previous translations to complete. DRENG */ - __asm__ __volatile__ ("isync" : : : "memory" ); + asm volatile("isync" : : : "memory" ); castout_ste->dw0.dw0.v = 0; - __asm__ __volatile__ ("sync" : : : "memory" ); /* Order update */ + asm volatile("sync" : : : "memory" ); /* Order update */ castout_ste->dw1.dw1.vsid = vsid; - __asm__ __volatile__ ("eieio" : : : "memory" ); /* Order update */ old_esid = castout_ste->dw0.dw0.esid; castout_ste->dw0.dw0.esid = esid; - castout_ste->dw0.dw0.v = 1; castout_ste->dw0.dw0.kp = 1; - __asm__ __volatile__ ("slbie %0" : : "r" (old_esid << SID_SHIFT)); + asm volatile("eieio" : : : "memory" ); /* Order update */ + castout_ste->dw0.dw0.v = 1; + asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT)); /* Ensure completion of slbie */ - __asm__ __volatile__ ("sync" : : : "memory" ); + asm volatile("sync" : : : "memory" ); - return(global_entry | (castout_entry & 0x7)); + return (global_entry | (castout_entry & 0x7)); } /* @@ -165,10 +161,10 @@ /* * Find an empty entry, if one exists. */ - for(entry = 0; entry < naca->slb_size; entry++) { - __asm__ __volatile__("slbmfee %0,%1" - : "=r" (esid_data) : "r" (entry)); - if(!esid_data.data.v) { + for (entry = 0; entry < naca->slb_size; entry++) { + asm volatile("slbmfee %0,%1" + : "=r" (esid_data) : "r" (entry)); + if (!esid_data.data.v) { /* * Write the new SLB entry. */ @@ -187,16 +183,16 @@ /* slbie not needed as no previous mapping existed. */ /* Order update */ - __asm__ __volatile__ ("isync" : : : "memory"); - __asm__ __volatile__ ("slbmte %0,%1" - : : "r" (vsid_data), - "r" (esid_data)); + asm volatile("isync" : : : "memory"); + asm volatile("slbmte %0,%1" + : : "r" (vsid_data), + "r" (esid_data)); /* Order update */ - __asm__ __volatile__ ("isync" : : : "memory"); + asm volatile("isync" : : : "memory"); return; } } - + /* * Could not find empty entry, pick one with a round robin selection. */ @@ -222,23 +218,50 @@ vsid_data.data.l = 1; if (kernel_segment) vsid_data.data.c = 1; - + esid_data.word0 = 0; esid_data.data.esid = esid; esid_data.data.v = 1; esid_data.data.index = entry; - - __asm__ __volatile__ ("isync" : : : "memory"); /* Order update */ - __asm__ __volatile__ ("slbmte %0,%1" - : : "r" (vsid_data), "r" (esid_data)); - __asm__ __volatile__ ("isync" : : : "memory" ); /* Order update */ + + asm volatile("isync" : : : "memory"); /* Order update */ + asm volatile("slbmte %0,%1" + : : "r" (vsid_data), "r" (esid_data)); + asm volatile("isync" : : : "memory" ); /* Order update */ +} + +static inline void __ste_allocate(unsigned long esid, unsigned long vsid, + int kernel_segment) +{ + if (cpu_has_slb()) { +#ifndef CONFIG_PPC_ISERIES + if (REGION_ID(esid << SID_SHIFT) == KERNEL_REGION_ID) + make_slbe(esid, vsid, 1); + else +#endif + make_slbe(esid, vsid, 0); + } else { + unsigned char top_entry, stab_entry, *segments; + + stab_entry = make_ste(get_paca()->xStab_data.virt, esid, vsid); + PMC_SW_PROCESSOR_A(stab_entry_use, stab_entry & 0xf); + + segments = get_paca()->xSegments; + top_entry = get_paca()->stab_cache_pointer; + if (!kernel_segment && top_entry < STAB_CACHE_SIZE) { + segments[top_entry] = stab_entry; + if (top_entry == STAB_CACHE_SIZE) + top_entry = 0xff; + top_entry++; + get_paca()->stab_cache_pointer = top_entry; + } + } } /* * Allocate a segment table entry for the given ea. */ -int ste_allocate ( unsigned long ea, - unsigned long trap) +int ste_allocate(unsigned long ea) { unsigned long vsid, esid; int kernel_segment = 0; @@ -246,87 +269,142 @@ PMC_SW_PROCESSOR(stab_faults); /* Check for invalid effective addresses. */ - if (!IS_VALID_EA(ea)) { + if (!IS_VALID_EA(ea)) return 1; - } - + /* Kernel or user address? */ if (REGION_ID(ea) >= KERNEL_REGION_ID) { kernel_segment = 1; - vsid = get_kernel_vsid( ea ); + vsid = get_kernel_vsid(ea); } else { struct mm_struct *mm = current->mm; - if ( mm ) { - vsid = get_vsid(mm->context, ea ); - } else { + if (mm) + vsid = get_vsid(mm->context, ea); + else return 1; - } } esid = GET_ESID(ea); - if (trap == 0x380 || trap == 0x480) { -#ifndef CONFIG_PPC_ISERIES - if (REGION_ID(ea) == KERNEL_REGION_ID) - make_slbe(esid, vsid, 1); - else -#endif - make_slbe(esid, vsid, 0); - } else { - unsigned char top_entry, stab_entry, *segments; + __ste_allocate(esid, vsid, kernel_segment); + if (!cpu_has_slb()) { + /* Order update */ + asm volatile("sync":::"memory"); + } - stab_entry = make_ste(get_paca()->xStab_data.virt, esid, vsid); - PMC_SW_PROCESSOR_A(stab_entry_use, stab_entry & 0xf); + return 0; +} - segments = get_paca()->xSegments; - top_entry = segments[0]; - if(!kernel_segment && top_entry < (STAB_CACHE_SIZE - 1)) { - top_entry++; - segments[top_entry] = stab_entry; - if(top_entry == STAB_CACHE_SIZE - 1) top_entry = 0xff; - segments[0] = top_entry; +unsigned long ppc64_preload_all_segments; +unsigned long ppc64_stab_preload = 1; +#define STAB_PRESSURE 0 +#define USE_SLBIE_ON_STAB 0 + +/* + * preload all 16 segments for a 32 bit process and the PC and SP segments + * for a 64 bit process. + */ +static void preload_stab(struct task_struct *tsk, struct mm_struct *mm) +{ + if (ppc64_preload_all_segments && test_tsk_thread_flag(tsk, TIF_32BIT)) { + unsigned long esid, vsid; + + for (esid = 0; esid < 16; esid++) { + vsid = get_vsid(mm->context, esid << SID_SHIFT); + __ste_allocate(esid, vsid, 0); + } + } else { + unsigned long pc = KSTK_EIP(tsk); + unsigned long stack = KSTK_ESP(tsk); + unsigned long pc_segment = pc & ~SID_MASK; + unsigned long stack_segment = stack & ~SID_MASK; + unsigned long vsid; + + if (pc) { + if (REGION_ID(pc) >= KERNEL_REGION_ID) + BUG(); + vsid = get_vsid(mm->context, pc); + __ste_allocate(GET_ESID(pc), vsid, 0); + } + + if (stack && (pc_segment != stack_segment)) { + if (REGION_ID(stack) >= KERNEL_REGION_ID) + BUG(); + vsid = get_vsid(mm->context, stack); + __ste_allocate(GET_ESID(stack), vsid, 0); } } - - return(0); -} - -/* - * Flush all entries from the segment table of the current processor. - * Kernel and Bolted entries are not removed as we cannot tolerate - * faults on those addresses. - */ -#define STAB_PRESSURE 0 + if (!cpu_has_slb()) { + /* Order update */ + asm volatile("sync" : : : "memory"); + } +} +/* Flush all user entries from the segment table of the current processor. */ void flush_stab(struct task_struct *tsk, struct mm_struct *mm) { - STE *stab = (STE *) get_paca()->xStab_data.virt; - unsigned char *segments = get_paca()->xSegments; - unsigned long flags, i; + if (cpu_has_slb()) { + if (!STAB_PRESSURE && test_thread_flag(TIF_32BIT)) { + union { + unsigned long word0; + slb_dword0 data; + } esid_data; + unsigned long esid; - if(!__is_processor(PV_POWER4)) { - unsigned long entry; + asm volatile("isync" : : : "memory"); + for (esid = 0; esid < 16; esid++) { + esid_data.word0 = 0; + esid_data.data.esid = esid; + asm volatile("slbie %0" : : "r" (esid_data)); + } + asm volatile("isync" : : : "memory"); + } else { + asm volatile("isync; slbia; isync":::"memory"); + } + + PMC_SW_PROCESSOR(stab_invalidations); + } else { + STE *stab = (STE *) get_paca()->xStab_data.virt; STE *ste; + unsigned long flags; /* Force previous translations to complete. DRENG */ - __asm__ __volatile__ ("isync" : : : "memory"); + asm volatile("isync" : : : "memory"); __save_and_cli(flags); - if(segments[0] != 0xff && !STAB_PRESSURE) { - for(i = 1; i <= segments[0]; i++) { + if (get_paca()->stab_cache_pointer != 0xff && !STAB_PRESSURE) { + int i; + unsigned char *segments = get_paca()->xSegments; + + for (i = 0; i < get_paca()->stab_cache_pointer; i++) { ste = stab + segments[i]; ste->dw0.dw0.v = 0; PMC_SW_PROCESSOR(stab_invalidations); } + +#if USE_SLBIE_ON_STAB + asm volatile("sync":::"memory"); + for (i = 0; i < get_paca()->stab_cache_pointer; i++) { + ste = stab + segments[i]; + asm volatile("slbie %0" : : + "r" (ste->dw0.dw0.esid << SID_SHIFT)); + } + asm volatile("sync":::"memory"); +#else + asm volatile("sync; slbia; sync":::"memory"); +#endif + } else { + unsigned long entry; + /* Invalidate all entries. */ - ste = stab; + ste = stab; - /* Never flush the first entry. */ - ste += 1; - for(entry = 1; - entry < (PAGE_SIZE / sizeof(STE)); - entry++, ste++) { + /* Never flush the first entry. */ + ste += 1; + for (entry = 1; + entry < (PAGE_SIZE / sizeof(STE)); + entry++, ste++) { unsigned long ea; ea = ste->dw0.dw0.esid << SID_SHIFT; if (STAB_PRESSURE || ea < KERNELBASE) { @@ -334,70 +412,14 @@ PMC_SW_PROCESSOR(stab_invalidations); } } - } - - *((unsigned long *)segments) = 0; - __restore_flags(flags); - /* Invalidate the SLB. */ - /* Force invals to complete. */ - __asm__ __volatile__ ("sync" : : : "memory"); - /* Flush the SLB. */ - __asm__ __volatile__ ("slbia" : : : "memory"); - /* Force flush to complete. */ - __asm__ __volatile__ ("sync" : : : "memory"); - } else { -/* XXX The commented out code will only work for 32 bit tasks */ -#if 1 - unsigned long flags; - __save_and_cli(flags); - __asm__ __volatile__("isync; slbia; isync":::"memory"); - __restore_flags(flags); -#else - union { - unsigned long word0; - slb_dword0 data; - } esid_data; - unsigned long esid; - - __asm__ __volatile__("isync" : : : "memory"); - for (esid = 0; esid < 16; esid++) { - esid_data.word0 = 0; - esid_data.data.esid = esid; - __asm__ __volatile__("slbie %0" : : "r" (esid_data)); + asm volatile("sync; slbia; sync":::"memory"); } - __asm__ __volatile__("isync" : : : "memory"); -#endif - - PMC_SW_PROCESSOR(stab_invalidations); - - if (test_tsk_thread_flag(tsk, TIF_32BIT)) { - unsigned long esid, vsid; - for (esid = 0; esid < 16; esid++) { - vsid = get_vsid(mm->context, esid << SID_SHIFT); - make_slbe(esid, vsid, 0); - } - } else { - unsigned long pc = KSTK_EIP(tsk); - unsigned long stack = KSTK_ESP(tsk); - unsigned long pc_segment = pc & ~SID_MASK; - unsigned long stack_segment = stack & ~SID_MASK; - unsigned long vsid; - - if (pc) { - if (REGION_ID(pc) >= KERNEL_REGION_ID) - BUG(); - vsid = get_vsid(mm->context, pc); - make_slbe(GET_ESID(pc), vsid, 0); - } - - if (stack && (pc_segment != stack_segment)) { - if (REGION_ID(stack) >= KERNEL_REGION_ID) - BUG(); - vsid = get_vsid(mm->context, stack); - make_slbe(GET_ESID(stack), vsid, 0); - } - } + get_paca()->stab_cache_pointer = 0; + __restore_flags(flags); } + + if (ppc64_stab_preload) + preload_stab(tsk, mm); } diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Sun Jun 2 18:44:58 2002 +++ b/arch/ppc64/kernel/sys_ppc32.c Sun Jun 2 18:44:58 2002 @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -66,6 +65,7 @@ #include #include #include +#include extern unsigned long wall_jiffies; #define USEC_PER_SEC (1000000) @@ -518,68 +518,6 @@ __kernel_time_t32 dqb_itime; }; - -extern asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr); - -/* Note: it is necessary to treat cmd and id as unsigned ints, - * with the corresponding cast to a signed int to insure that the - * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) - * and the register representation of a signed int (msr in 64-bit mode) is performed. - */ -asmlinkage long sys32_quotactl(u32 cmd_parm, const char *special, u32 id_parm, unsigned long addr) -{ - int cmd = (int)cmd_parm; - int id = (int)id_parm; - int cmds = cmd >> SUBCMDSHIFT; - int err; - struct dqblk d; - mm_segment_t old_fs; - char *spec; - - PPCDBG(PPCDBG_SYS32, "sys32_quotactl - entered - pid=%ld current=%lx comm=%s \n", - current->pid, current, current->comm); - - switch (cmds) { - case Q_GETQUOTA: - break; - case Q_SETQUOTA: - case Q_SETUSE: - case Q_SETQLIM: - if (copy_from_user (&d, (struct dqblk32 *)addr, - sizeof (struct dqblk32))) - return -EFAULT; - d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime; - d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime; - break; - default: - return sys_quotactl(cmd, special, - id, (caddr_t)addr); - } - spec = getname32 (special); - err = PTR_ERR(spec); - if (IS_ERR(spec)) return err; - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d); - set_fs (old_fs); - putname (spec); - if (cmds == Q_GETQUOTA) { - __kernel_time_t b = d.dqb_btime, i = d.dqb_itime; - ((struct dqblk32 *)&d)->dqb_itime = i; - ((struct dqblk32 *)&d)->dqb_btime = b; - if (copy_to_user ((struct dqblk32 *)addr, &d, - sizeof (struct dqblk32))) - return -EFAULT; - } - - PPCDBG(PPCDBG_SYS32, "sys32_quotactl - exited - pid=%ld current=%lx comm=%s \n", - current->pid, current, current->comm); - - return err; -} - - - /* readdir & getdents */ #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) #define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1)) @@ -900,15 +838,6 @@ return ret; } - - - -/* - * Due to some executables calling the wrong select we sometimes - * get wrong args. This determines how the args are being passed - * (a single ptr to them all args passed) then calls - * sys_select() with the appropriate args. -- Cort - */ /* Note: it is necessary to treat n as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -916,14 +845,9 @@ */ asmlinkage int ppc32_select(u32 n, u32* inp, u32* outp, u32* exp, u32 tvp_x) { - if ((unsigned int)n >= 4096) - panic("ppc32_select - wrong arguments were passed in \n"); - return sys32_select((int)n, inp, outp, exp, tvp_x); } - - static int cp_new_stat32(struct kstat *stat, struct stat32 *statbuf) { int err; @@ -3800,63 +3724,76 @@ int retval; int i; - bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); - memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); - file = open_exec(filename); retval = PTR_ERR(file); if (IS_ERR(file)) return retval; + bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); + memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); + bprm.file = file; bprm.filename = filename; bprm.sh_bang = 0; bprm.loader = 0; bprm.exec = 0; - if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) { - allow_write_access(file); - fput(file); - return bprm.argc; - } - if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) { - allow_write_access(file); - fput(file); - return bprm.argc; - } - - retval = prepare_binprm(&bprm); + + bprm.mm = mm_alloc(); + retval = -ENOMEM; + if (!bprm.mm) + goto out_file; + + retval = init_new_context(current, bprm.mm); if (retval < 0) - goto out; - + goto out_mm; + + bprm.argc = count32(argv, bprm.p / sizeof(u32)); + if ((retval = bprm.argc) < 0) + goto out_mm; + + bprm.envc = count32(envp, bprm.p / sizeof(u32)); + if ((retval = bprm.envc) < 0) + goto out_mm; + + retval = prepare_binprm(&bprm); + if (retval < 0) + goto out; + retval = copy_strings_kernel(1, &bprm.filename, &bprm); - if (retval < 0) - goto out; + if (retval < 0) + goto out; bprm.exec = bprm.p; retval = copy_strings32(bprm.envc, envp, &bprm); - if (retval < 0) - goto out; + if (retval < 0) + goto out; retval = copy_strings32(bprm.argc, argv, &bprm); - if (retval < 0) - goto out; + if (retval < 0) + goto out; - retval = search_binary_handler(&bprm, regs); + retval = search_binary_handler(&bprm,regs); if (retval >= 0) /* execve success */ return retval; out: /* Something went wrong, return the inode and free the argument pages*/ - allow_write_access(bprm.file); - if (bprm.file) - fput(bprm.file); - - for (i=0 ; ipid, current->comm); - //PPCDBG(PPCDBG_SYS32NI, " a0=%lx, a1=%lx, a2=%lx, a3=%lx, a4=%lx, a5=%lx, regs=%p \n", a0, a1, a2, a3, a4, a5, regs); - } - filename = getname((char *) a0); error = PTR_ERR(filename); if (IS_ERR(filename)) @@ -3886,10 +3818,6 @@ putname(filename); out: - ifppcdebug(PPCDBG_SYS32) { - udbg_printf("sys32_execve - exited - returning %x - pid=%ld \n", error, current->pid); - //udbg_printf("sys32_execve - at exit - regs->gpr[1]=%lx, gpr[3]=%lx, gpr[4]=%lx, gpr[5]=%lx, gpr[6]=%lx \n", regs->gpr[1], regs->gpr[3], regs->gpr[4], regs->gpr[5], regs->gpr[6]); - } return error; } @@ -4670,4 +4598,54 @@ } return secs; +} + +extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len, + unsigned long *user_mask_ptr); + +asmlinkage int sys32_sched_setaffinity(__kernel_pid_t32 pid, unsigned int len, + u32 *user_mask_ptr) +{ + unsigned long kernel_mask; + mm_segment_t old_fs; + int ret; + + if (get_user(kernel_mask, user_mask_ptr)) + return -EFAULT; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_sched_setaffinity(pid, + /* XXX Nice api... */ + sizeof(kernel_mask), + &kernel_mask); + set_fs(old_fs); + + return ret; +} + +extern asmlinkage int sys_sched_getaffinity(pid_t pid, unsigned int len, + unsigned long *user_mask_ptr); + +asmlinkage int sys32_sched_getaffinity(__kernel_pid_t32 pid, unsigned int len, + u32 *user_mask_ptr) +{ + unsigned long kernel_mask; + mm_segment_t old_fs; + int ret; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_sched_getaffinity(pid, + /* XXX Nice api... */ + sizeof(kernel_mask), + &kernel_mask); + set_fs(old_fs); + + if (ret == 0) { + if (put_user(kernel_mask, user_mask_ptr)) + ret = -EFAULT; + } + + return ret; } diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c --- a/arch/ppc64/kernel/traps.c Sun Jun 2 18:44:57 2002 +++ b/arch/ppc64/kernel/traps.c Sun Jun 2 18:44:57 2002 @@ -38,29 +38,12 @@ #include extern int fix_alignment(struct pt_regs *); -extern void bad_page_fault(struct pt_regs *, unsigned long); +extern void bad_page_fault(struct pt_regs *, unsigned long, int); /* This is true if we are using the firmware NMI handler (typically LPAR) */ extern int fwnmi_active; -#ifdef CONFIG_XMON -extern void xmon(struct pt_regs *regs); -extern int xmon_bpt(struct pt_regs *regs); -extern int xmon_sstep(struct pt_regs *regs); -extern int xmon_iabr_match(struct pt_regs *regs); -extern int xmon_dabr_match(struct pt_regs *regs); -extern void (*xmon_fault_handler)(struct pt_regs *regs); -#endif - -#ifdef CONFIG_XMON -void (*debugger)(struct pt_regs *regs) = xmon; -int (*debugger_bpt)(struct pt_regs *regs) = xmon_bpt; -int (*debugger_sstep)(struct pt_regs *regs) = xmon_sstep; -int (*debugger_iabr_match)(struct pt_regs *regs) = xmon_iabr_match; -int (*debugger_dabr_match)(struct pt_regs *regs) = xmon_dabr_match; -void (*debugger_fault_handler)(struct pt_regs *regs); -#else -#ifdef CONFIG_KGDB +#ifdef CONFIG_DEBUG_KERNEL void (*debugger)(struct pt_regs *regs); int (*debugger_bpt)(struct pt_regs *regs); int (*debugger_sstep)(struct pt_regs *regs); @@ -68,30 +51,44 @@ int (*debugger_dabr_match)(struct pt_regs *regs); void (*debugger_fault_handler)(struct pt_regs *regs); #endif -#endif + /* * Trap & Exception support */ -void -_exception(int signr, struct pt_regs *regs) +/* Should we panic on bad kernel exceptions or try to recover */ +#undef PANIC_ON_ERROR + +static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; + +void die(const char *str, struct pt_regs *regs, long err) { - if (!user_mode(regs)) - { - show_regs(regs); -#if defined(CONFIG_XMON) || defined(CONFIG_KGDB) - debugger(regs); + console_verbose(); + spin_lock_irq(&die_lock); + bust_spinlocks(1); + printk("Oops: %s, sig: %ld\n", str, err); + show_regs(regs); + print_backtrace((unsigned long *)regs->gpr[1]); + bust_spinlocks(0); + spin_unlock_irq(&die_lock); + +#ifdef PANIC_ON_ERROR + panic(str); +#else + do_exit(SIGSEGV); #endif - print_backtrace((unsigned long *)regs->gpr[1]); - panic("Exception in kernel pc %lx signal %d",regs->nip,signr); -#if defined(CONFIG_PPCDBG) && (defined(CONFIG_XMON) || defined(CONFIG_KGDB)) - /* Allow us to catch SIGILLs for 64-bit app/glibc debugging. -Peter */ - } else if (signr == SIGILL) { - ifppcdebug(PPCDBG_SIGNALXMON) +} + +static void +_exception(int signr, siginfo_t *info, struct pt_regs *regs) +{ + if (!user_mode(regs)) { + if (debugger) debugger(regs); -#endif + die("Exception in kernel mode\n", regs, signr); } - force_sig(signr, current); + + force_sig_info(signr, info, current); } /* Get the error information for errors coming through the @@ -130,9 +127,8 @@ void SystemResetException(struct pt_regs *regs) { - char *msg = "System Reset in kernel mode.\n"; - udbg_printf(msg); printk(msg); if (fwnmi_active) { + char *msg; unsigned long *r3 = __va(regs->gpr[3]); /* for FWNMI debug */ struct rtas_error_log *errlog; @@ -140,17 +136,31 @@ udbg_printf(msg, r3); printk(msg, r3); errlog = FWNMI_get_errinfo(regs); } -#if defined(CONFIG_XMON) - xmon(regs); - udbg_printf("leaving xmon...\n"); + + if (debugger) + debugger(regs); + +#ifdef PANIC_ON_ERROR + panic("System Reset"); #else - for(;;); + /* Must die if the interrupt is not recoverable */ + if (!(regs->msr & MSR_RI)) + panic("Unrecoverable System Reset"); #endif + + /* What should we do here? We could issue a shutdown or hard reset. */ +} + +static int power4_handle_mce(struct pt_regs *regs) +{ + return 0; } void MachineCheckException(struct pt_regs *regs) { + siginfo_t info; + if (fwnmi_active) { struct rtas_error_log *errhdr = FWNMI_get_errinfo(regs); if (errhdr) { @@ -158,117 +168,221 @@ } FWNMI_release_errinfo(); } - if ( !user_mode(regs) ) - { -#if defined(CONFIG_XMON) || defined(CONFIG_KGDB) + + if (!user_mode(regs)) { + /* Attempt to recover if the interrupt is recoverable */ + if (regs->msr & MSR_RI) { + if (__is_processor(PV_POWER4) && + power4_handle_mce(regs)) + return; + } + if (debugger_fault_handler) { debugger_fault_handler(regs); return; } -#endif + if (debugger) + debugger(regs); + + console_verbose(); + spin_lock_irq(&die_lock); + bust_spinlocks(1); printk("Machine check in kernel mode.\n"); printk("Caused by (from SRR1=%lx): ", regs->msr); show_regs(regs); -#if defined(CONFIG_XMON) || defined(CONFIG_KGDB) - debugger(regs); -#endif print_backtrace((unsigned long *)regs->gpr[1]); - panic("machine check"); + bust_spinlocks(0); + spin_unlock_irq(&die_lock); + panic("Unrecoverable Machine Check"); } - _exception(SIGSEGV, regs); -} -void -SMIException(struct pt_regs *regs) -{ -#if defined(CONFIG_XMON) || defined(CONFIG_KGDB) - { - debugger(regs); - return; - } -#endif - show_regs(regs); - print_backtrace((unsigned long *)regs->gpr[1]); - panic("System Management Interrupt"); + /* + * XXX we should check RI bit on exception exit and kill the + * task if it was cleared + */ + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void *)regs->nip; + _exception(SIGSEGV, &info, regs); } void UnknownException(struct pt_regs *regs) { + siginfo_t info; + printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", regs->nip, regs->msr, regs->trap); - _exception(SIGTRAP, regs); + + info.si_signo = SIGTRAP; + info.si_errno = 0; + info.si_code = 0; + info.si_addr = 0; + _exception(SIGTRAP, &info, regs); } void InstructionBreakpointException(struct pt_regs *regs) { -#if defined(CONFIG_XMON) || defined(CONFIG_KGDB) - if (debugger_iabr_match(regs)) + siginfo_t info; + + if (debugger_iabr_match && debugger_iabr_match(regs)) return; -#endif - _exception(SIGTRAP, regs); + + info.si_signo = SIGTRAP; + info.si_errno = 0; + info.si_code = TRAP_BRKPT; + info.si_addr = (void *)regs->nip; + _exception(SIGTRAP, &info, regs); +} + +static void parse_fpe(struct pt_regs *regs) +{ + siginfo_t info; + unsigned int *tmp; + unsigned int fpscr; + + if (regs->msr & MSR_FP) + giveup_fpu(current); + + tmp = ¤t->thread.fpscr; + fpscr = *tmp; + + /* Invalid operation */ + if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX)) + info.si_code = FPE_FLTINV; + + /* Overflow */ + else if ((fpscr & FPSCR_OE) && (fpscr & FPSCR_OX)) + info.si_code = FPE_FLTOVF; + + /* Underflow */ + else if ((fpscr & FPSCR_UE) && (fpscr & FPSCR_UX)) + info.si_code = FPE_FLTUND; + + /* Divide by zero */ + else if ((fpscr & FPSCR_ZE) && (fpscr & FPSCR_ZX)) + info.si_code = FPE_FLTDIV; + + /* Inexact result */ + else if ((fpscr & FPSCR_XE) && (fpscr & FPSCR_XX)) + info.si_code = FPE_FLTRES; + + else + info.si_code = 0; + + info.si_signo = SIGFPE; + info.si_errno = 0; + info.si_addr = (void *)regs->nip; + _exception(SIGFPE, &info, regs); } void ProgramCheckException(struct pt_regs *regs) { + siginfo_t info; + if (regs->msr & 0x100000) { /* IEEE FP exception */ - _exception(SIGFPE, regs); + + parse_fpe(regs); + } else if (regs->msr & 0x40000) { + /* Privileged instruction */ + + info.si_signo = SIGILL; + info.si_errno = 0; + info.si_code = ILL_PRVOPC; + info.si_addr = (void *)regs->nip; + _exception(SIGILL, &info, regs); } else if (regs->msr & 0x20000) { /* trap exception */ -#if defined(CONFIG_XMON) || defined(CONFIG_KGDB) - if (debugger_bpt(regs)) + + if (debugger_bpt && debugger_bpt(regs)) return; -#endif - _exception(SIGTRAP, regs); + + info.si_signo = SIGTRAP; + info.si_errno = 0; + info.si_code = TRAP_BRKPT; + info.si_addr = (void *)regs->nip; + _exception(SIGTRAP, &info, regs); } else { - _exception(SIGILL, regs); + /* Illegal instruction */ + + info.si_signo = SIGILL; + info.si_errno = 0; + info.si_code = ILL_ILLTRP; + info.si_addr = (void *)regs->nip; + _exception(SIGILL, &info, regs); } } void SingleStepException(struct pt_regs *regs) { + siginfo_t info; + regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ -#if defined(CONFIG_XMON) || defined(CONFIG_KGDB) - if (debugger_sstep(regs)) + + if (debugger_sstep && debugger_sstep(regs)) return; -#endif - _exception(SIGTRAP, regs); -} -/* Dummy handler for Performance Monitor */ + info.si_signo = SIGTRAP; + info.si_errno = 0; + info.si_code = TRAP_TRACE; + info.si_addr = (void *)regs->nip; + _exception(SIGTRAP, &info, regs); +} void PerformanceMonitorException(struct pt_regs *regs) { - _exception(SIGTRAP, regs); + siginfo_t info; + + info.si_signo = SIGTRAP; + info.si_errno = 0; + info.si_code = TRAP_BRKPT; + info.si_addr = 0; + _exception(SIGTRAP, &info, regs); } void AlignmentException(struct pt_regs *regs) { int fixed; + siginfo_t info; fixed = fix_alignment(regs); + if (fixed == 1) { - ifppcdebug(PPCDBG_ALIGNFIXUP) - if (!user_mode(regs)) - PPCDBG(PPCDBG_ALIGNFIXUP, "fix alignment at %lx\n", regs->nip); + if (!user_mode(regs)) + PPCDBG(PPCDBG_ALIGNFIXUP, "fix alignment at %lx\n", + regs->nip); regs->nip += 4; /* skip over emulated instruction */ return; } + + /* Operand address was bad */ if (fixed == -EFAULT) { - /* fixed == -EFAULT means the operand address was bad */ - if (user_mode(regs)) - force_sig(SIGSEGV, current); - else - bad_page_fault(regs, regs->dar); + if (user_mode(regs)) { + info.si_signo = SIGSEGV; + info.si_errno = 0; + info.si_code = SEGV_MAPERR; + info.si_addr = (void *)regs->dar; + force_sig_info(SIGSEGV, &info, current); + } else { + /* Search exception table */ + bad_page_fault(regs, regs->dar, SIGSEGV); + } + return; } - _exception(SIGBUS, regs); + + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRALN; + info.si_addr = (void *)regs->nip; + _exception(SIGBUS, &info, regs); } void __init trap_init(void) diff -Nru a/arch/ppc64/lib/Makefile b/arch/ppc64/lib/Makefile --- a/arch/ppc64/lib/Makefile Sun Jun 2 18:44:56 2002 +++ b/arch/ppc64/lib/Makefile Sun Jun 2 18:44:56 2002 @@ -4,6 +4,7 @@ O_TARGET = lib.o -obj-y := checksum.o dec_and_lock.o string.o strcase.o +obj-y := checksum.o dec_and_lock.o string.o strcase.o copypage.o \ + memcpy.o copyuser.o include $(TOPDIR)/Rules.make diff -Nru a/arch/ppc64/lib/copypage.S b/arch/ppc64/lib/copypage.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/lib/copypage.S Sun Jun 2 18:44:58 2002 @@ -0,0 +1,121 @@ +/* + * arch/ppc64/lib/copypage.S + * + * Copyright (C) 2002 Paul Mackerras, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include "../kernel/ppc_asm.h" + +_GLOBAL(copy_page) + std r31,-8(1) + std r30,-16(1) + std r29,-24(1) + std r28,-32(1) + std r27,-40(1) + std r26,-48(1) + std r25,-56(1) + std r24,-64(1) + std r23,-72(1) + std r22,-80(1) + std r21,-88(1) + std r20,-96(1) + li r5,4096/32 - 1 + addi r3,r3,-8 + li r12,5 +0: addi r5,r5,-24 + mtctr r12 + ld r22,640(4) + ld r21,512(4) + ld r20,384(4) + ld r11,256(4) + ld r9,128(4) + ld r7,0(4) + ld r25,648(4) + ld r24,520(4) + ld r23,392(4) + ld r10,264(4) + ld r8,136(4) + ldu r6,8(4) + cmpwi r5,24 +1: std r22,648(3) + std r21,520(3) + std r20,392(3) + std r11,264(3) + std r9,136(3) + std r7,8(3) + ld r28,648(4) + ld r27,520(4) + ld r26,392(4) + ld r31,264(4) + ld r30,136(4) + ld r29,8(4) + std r25,656(3) + std r24,528(3) + std r23,400(3) + std r10,272(3) + std r8,144(3) + std r6,16(3) + ld r22,656(4) + ld r21,528(4) + ld r20,400(4) + ld r11,272(4) + ld r9,144(4) + ld r7,16(4) + std r28,664(3) + std r27,536(3) + std r26,408(3) + std r31,280(3) + std r30,152(3) + stdu r29,24(3) + ld r25,664(4) + ld r24,536(4) + ld r23,408(4) + ld r10,280(4) + ld r8,152(4) + ldu r6,24(4) + bdnz 1b + std r22,648(3) + std r21,520(3) + std r20,392(3) + std r11,264(3) + std r9,136(3) + std r7,8(3) + addi r4,r4,640 + addi r3,r3,648 + bge 0b + mtctr r5 + ld r7,0(4) + ld r8,8(4) + ldu r9,16(4) +3: ld r10,8(4) + std r7,8(3) + ld r7,16(4) + std r8,16(3) + ld r8,24(4) + std r9,24(3) + ldu r9,32(4) + stdu r10,32(3) + bdnz 3b +4: ld r10,8(4) + std r7,8(3) + std r8,16(3) + std r9,24(3) + std r10,32(3) +9: ld r20,-96(1) + ld r21,-88(1) + ld r22,-80(1) + ld r23,-72(1) + ld r24,-64(1) + ld r25,-56(1) + ld r26,-48(1) + ld r27,-40(1) + ld r28,-32(1) + ld r29,-24(1) + ld r30,-16(1) + ld r31,-8(1) + blr diff -Nru a/arch/ppc64/lib/copyuser.S b/arch/ppc64/lib/copyuser.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/lib/copyuser.S Sun Jun 2 18:44:58 2002 @@ -0,0 +1,562 @@ +/* + * arch/ppc64/lib/copyuser.S + * + * Copyright (C) 2002 Paul Mackerras, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include "../kernel/ppc_asm.h" + + .align 7 +_GLOBAL(__copy_tofrom_user) + /* first check for a whole page copy on a page boundary */ + cmpldi cr1,r5,16 + cmpdi cr6,r5,4096 + or r0,r3,r4 + neg r6,r3 /* LS 3 bits = # bytes to 8-byte dest bdry */ + andi. r0,r0,4095 + std r3,-24(r1) + crand cr0*4+2,cr0*4+2,cr6*4+2 + std r4,-16(r1) + std r5,-8(r1) + dcbt 0,r4 + beq .Lcopy_page + andi. r6,r6,7 + mtcrf 0x01,r5 + blt cr1,.Lshort_copy + bne .Ldst_unaligned +.Ldst_aligned: + andi. r0,r4,7 + addi r3,r3,-16 + bne .Lsrc_unaligned + srdi r7,r5,4 +20: ld r9,0(r4) + addi r4,r4,-8 + mtctr r7 + andi. r5,r5,7 + bf cr7*4+0,22f + addi r3,r3,8 + addi r4,r4,8 + mr r8,r9 + blt cr1,72f +21: ld r9,8(r4) +70: std r8,8(r3) +22: ldu r8,16(r4) +71: stdu r9,16(r3) + bdnz 21b +72: std r8,8(r3) + beq+ 3f + addi r3,r3,16 +23: ld r9,8(r4) +.Ldo_tail: + bf cr7*4+1,1f + rotldi r9,r9,32 +73: stw r9,0(r3) + addi r3,r3,4 +1: bf cr7*4+2,2f + rotldi r9,r9,16 +74: sth r9,0(r3) + addi r3,r3,2 +2: bf cr7*4+3,3f + rotldi r9,r9,8 +75: stb r9,0(r3) +3: li r3,0 + blr + +.Lsrc_unaligned: + srdi r6,r5,3 + addi r5,r5,-16 + subf r4,r0,r4 + srdi r7,r5,4 + sldi r10,r0,3 + cmpldi cr6,r6,3 + andi. r5,r5,7 + mtctr r7 + subfic r11,r10,64 + add r5,r5,r0 + bt cr7*4+0,28f + +24: ld r9,0(r4) /* 3+2n loads, 2+2n stores */ +25: ld r0,8(r4) + sld r6,r9,r10 +26: ldu r9,16(r4) + srd r7,r0,r11 + sld r8,r0,r10 + or r7,r7,r6 + blt cr6,79f +27: ld r0,8(r4) + b 2f + +28: ld r0,0(r4) /* 4+2n loads, 3+2n stores */ +29: ldu r9,8(r4) + sld r8,r0,r10 + addi r3,r3,-8 + blt cr6,5f +30: ld r0,8(r4) + srd r12,r9,r11 + sld r6,r9,r10 +31: ldu r9,16(r4) + or r12,r8,r12 + srd r7,r0,r11 + sld r8,r0,r10 + addi r3,r3,16 + beq cr6,78f + +1: or r7,r7,r6 +32: ld r0,8(r4) +76: std r12,8(r3) +2: srd r12,r9,r11 + sld r6,r9,r10 +33: ldu r9,16(r4) + or r12,r8,r12 +77: stdu r7,16(r3) + srd r7,r0,r11 + sld r8,r0,r10 + bdnz 1b + +78: std r12,8(r3) + or r7,r7,r6 +79: std r7,16(r3) +5: srd r12,r9,r11 + or r12,r8,r12 +80: std r12,24(r3) + bne 6f + li r3,0 + blr +6: cmpwi cr1,r5,8 + addi r3,r3,32 + sld r9,r9,r10 + blt cr1,.Ldo_tail +34: ld r0,8(r4) + srd r7,r0,r11 + or r9,r7,r9 + b .Ldo_tail + +.Ldst_unaligned: + mtcrf 0x01,r6 /* put #bytes to 8B bdry into cr7 */ + subf r5,r6,r5 + li r7,0 + cmpldi r1,r5,16 + bf cr7*4+3,1f +35: lbz r0,0(r4) +81: stb r0,0(r3) + addi r7,r7,1 +1: bf cr7*4+2,2f +36: lhzx r0,r7,r4 +82: sthx r0,r7,r3 + addi r7,r7,2 +2: bf cr7*4+1,3f +37: lwzx r0,r7,r4 +83: stwx r0,r7,r3 +3: mtcrf 0x01,r5 + add r4,r6,r4 + add r3,r6,r3 + b .Ldst_aligned + +.Lshort_copy: + bf cr7*4+0,1f +38: lwz r0,0(r4) +39: lwz r9,4(r4) + addi r4,r4,8 +84: stw r0,0(r3) +85: stw r9,4(r3) + addi r3,r3,8 +1: bf cr7*4+1,2f +40: lwz r0,0(r4) + addi r4,r4,4 +86: stw r0,0(r3) + addi r3,r3,4 +2: bf cr7*4+2,3f +41: lhz r0,0(r4) + addi r4,r4,2 +87: sth r0,0(r3) + addi r3,r3,2 +3: bf cr7*4+3,4f +42: lbz r0,0(r4) +88: stb r0,0(r3) +4: li r3,0 + blr + +/* + * exception handlers follow + * we have to return the number of bytes not copied + * for an exception on a load, we set the rest of the destination to 0 + */ + +136: +137: + add r3,r3,r7 + b 1f +130: +131: + addi r3,r3,8 +120: +122: +124: +125: +126: +127: +128: +129: +133: + addi r3,r3,8 +121: +132: + addi r3,r3,8 +123: +134: +135: +138: +139: +140: +141: +142: + +/* + * here we have had a fault on a load and r3 points to the first + * unmodified byte of the destination + */ +1: ld r6,-24(r1) + ld r4,-16(r1) + ld r5,-8(r1) + subf r6,r6,r3 + add r4,r4,r6 + subf r5,r6,r5 /* #bytes left to go */ + +/* + * first see if we can copy any more bytes before hitting another exception + */ + mtctr r5 +43: lbz r0,0(r4) + addi r4,r4,1 +89: stb r0,0(r3) + addi r3,r3,1 + bdnz 43b + li r3,0 /* huh? all copied successfully this time? */ + blr + +/* + * here we have trapped again, need to clear ctr bytes starting at r3 + */ +143: mfctr r5 + li r0,0 + mr r4,r3 + mr r3,r5 /* return the number of bytes not copied */ +1: andi. r9,r4,7 + beq 3f +90: stb r0,0(r4) + addic. r5,r5,-1 + addi r4,r4,1 + bne 1b + blr +3: srdi r9,r5,3 + andi. r5,r5,7 + mtctr r9 +91: std r0,0(r4) + addi r4,r4,8 + bdnz 91b + beqlr + mtctr r5 +92: stb r0,0(r4) + addi r4,r4,1 + bdnz 92b + blr + +/* + * exception handlers for stores: we just need to work + * out how many bytes weren't copied + */ +182: +183: + add r3,r3,r7 + b 1f +180: + addi r3,r3,8 +171: +177: + addi r3,r3,8 +170: +172: +176: +178: + addi r3,r3,4 +185: + addi r3,r3,4 +173: +174: +175: +179: +181: +184: +186: +187: +188: +189: +1: + ld r6,-24(r1) + ld r5,-8(r1) + add r6,r6,r5 + subf r3,r3,r6 /* #bytes not copied */ +190: +191: +192: + blr /* #bytes not copied in r3 */ + + .section __ex_table,"a" + .align 3 + .llong 20b,120b + .llong 21b,121b + .llong 70b,170b + .llong 22b,122b + .llong 71b,171b + .llong 72b,172b + .llong 23b,123b + .llong 73b,173b + .llong 74b,174b + .llong 75b,175b + .llong 24b,124b + .llong 25b,125b + .llong 26b,126b + .llong 27b,127b + .llong 28b,128b + .llong 29b,129b + .llong 30b,130b + .llong 31b,131b + .llong 32b,132b + .llong 76b,176b + .llong 33b,133b + .llong 77b,177b + .llong 78b,178b + .llong 79b,179b + .llong 80b,180b + .llong 34b,134b + .llong 35b,135b + .llong 81b,181b + .llong 36b,136b + .llong 82b,182b + .llong 37b,137b + .llong 83b,183b + .llong 38b,138b + .llong 39b,139b + .llong 84b,184b + .llong 85b,185b + .llong 40b,140b + .llong 86b,186b + .llong 41b,141b + .llong 87b,187b + .llong 42b,142b + .llong 88b,188b + .llong 43b,143b + .llong 89b,189b + .llong 90b,190b + .llong 91b,191b + .llong 92b,192b + + .text + +/* + * Routine to copy a whole page of data, optimized for POWER4. + * On POWER4 it is more than 50% faster than the simple loop + * above (following the .Ldst_aligned label) but it runs slightly + * slower on POWER3. + */ +.Lcopy_page: + std r31,-32(1) + std r30,-40(1) + std r29,-48(1) + std r28,-56(1) + std r27,-64(1) + std r26,-72(1) + std r25,-80(1) + std r24,-88(1) + std r23,-96(1) + std r22,-104(1) + std r21,-112(1) + std r20,-120(1) + li r5,4096/32 - 1 + addi r3,r3,-8 + li r0,5 +0: addi r5,r5,-24 + mtctr r0 +20: ld r22,640(4) +21: ld r21,512(4) +22: ld r20,384(4) +23: ld r11,256(4) +24: ld r9,128(4) +25: ld r7,0(4) +26: ld r25,648(4) +27: ld r24,520(4) +28: ld r23,392(4) +29: ld r10,264(4) +30: ld r8,136(4) +31: ldu r6,8(4) + cmpwi r5,24 +1: +32: std r22,648(3) +33: std r21,520(3) +34: std r20,392(3) +35: std r11,264(3) +36: std r9,136(3) +37: std r7,8(3) +38: ld r28,648(4) +39: ld r27,520(4) +40: ld r26,392(4) +41: ld r31,264(4) +42: ld r30,136(4) +43: ld r29,8(4) +44: std r25,656(3) +45: std r24,528(3) +46: std r23,400(3) +47: std r10,272(3) +48: std r8,144(3) +49: std r6,16(3) +50: ld r22,656(4) +51: ld r21,528(4) +52: ld r20,400(4) +53: ld r11,272(4) +54: ld r9,144(4) +55: ld r7,16(4) +56: std r28,664(3) +57: std r27,536(3) +58: std r26,408(3) +59: std r31,280(3) +60: std r30,152(3) +61: stdu r29,24(3) +62: ld r25,664(4) +63: ld r24,536(4) +64: ld r23,408(4) +65: ld r10,280(4) +66: ld r8,152(4) +67: ldu r6,24(4) + bdnz 1b +68: std r22,648(3) +69: std r21,520(3) +70: std r20,392(3) +71: std r11,264(3) +72: std r9,136(3) +73: std r7,8(3) +74: addi r4,r4,640 +75: addi r3,r3,648 + bge 0b + mtctr r5 +76: ld r7,0(4) +77: ld r8,8(4) +78: ldu r9,16(4) +3: +79: ld r10,8(4) +80: std r7,8(3) +81: ld r7,16(4) +82: std r8,16(3) +83: ld r8,24(4) +84: std r9,24(3) +85: ldu r9,32(4) +86: stdu r10,32(3) + bdnz 3b +4: +87: ld r10,8(4) +88: std r7,8(3) +89: std r8,16(3) +90: std r9,24(3) +91: std r10,32(3) +9: ld r20,-120(1) + ld r21,-112(1) + ld r22,-104(1) + ld r23,-96(1) + ld r24,-88(1) + ld r25,-80(1) + ld r26,-72(1) + ld r27,-64(1) + ld r28,-56(1) + ld r29,-48(1) + ld r30,-40(1) + ld r31,-32(1) + li r3,0 + blr + +/* + * on an exception, reset to the beginning and jump back into the + * standard __copy_tofrom_user + */ +100: ld r3,-24(r1) + ld r4,-24(r1) + li r5,4096 + b .Ldst_aligned + + .section __ex_table,"a" + .align 3 + .llong 20b,100b + .llong 21b,100b + .llong 22b,100b + .llong 23b,100b + .llong 24b,100b + .llong 25b,100b + .llong 26b,100b + .llong 27b,100b + .llong 28b,100b + .llong 29b,100b + .llong 30b,100b + .llong 31b,100b + .llong 32b,100b + .llong 33b,100b + .llong 34b,100b + .llong 35b,100b + .llong 36b,100b + .llong 37b,100b + .llong 38b,100b + .llong 39b,100b + .llong 40b,100b + .llong 41b,100b + .llong 42b,100b + .llong 43b,100b + .llong 44b,100b + .llong 45b,100b + .llong 46b,100b + .llong 47b,100b + .llong 48b,100b + .llong 49b,100b + .llong 50b,100b + .llong 51b,100b + .llong 52b,100b + .llong 53b,100b + .llong 54b,100b + .llong 55b,100b + .llong 56b,100b + .llong 57b,100b + .llong 58b,100b + .llong 59b,100b + .llong 60b,100b + .llong 61b,100b + .llong 62b,100b + .llong 63b,100b + .llong 64b,100b + .llong 65b,100b + .llong 66b,100b + .llong 67b,100b + .llong 68b,100b + .llong 69b,100b + .llong 70b,100b + .llong 71b,100b + .llong 72b,100b + .llong 73b,100b + .llong 74b,100b + .llong 75b,100b + .llong 76b,100b + .llong 77b,100b + .llong 78b,100b + .llong 79b,100b + .llong 80b,100b + .llong 81b,100b + .llong 82b,100b + .llong 83b,100b + .llong 84b,100b + .llong 85b,100b + .llong 86b,100b + .llong 87b,100b + .llong 88b,100b + .llong 89b,100b + .llong 90b,100b + .llong 91b,100b diff -Nru a/arch/ppc64/lib/memcpy.S b/arch/ppc64/lib/memcpy.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/lib/memcpy.S Sun Jun 2 18:44:58 2002 @@ -0,0 +1,172 @@ +/* + * arch/ppc64/lib/memcpy.S + * + * Copyright (C) 2002 Paul Mackerras, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include "../kernel/ppc_asm.h" + + .align 7 +_GLOBAL(memcpy) + mtcrf 0x01,r5 + cmpldi cr1,r5,16 + neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry + andi. r6,r6,7 + dcbt 0,r4 + blt cr1,.Lshort_copy + bne .Ldst_unaligned +.Ldst_aligned: + andi. r0,r4,7 + addi r3,r3,-16 + bne .Lsrc_unaligned + srdi r7,r5,4 + ld r9,0(r4) + addi r4,r4,-8 + mtctr r7 + andi. r5,r5,7 + bf cr7*4+0,2f + addi r3,r3,8 + addi r4,r4,8 + mr r8,r9 + blt cr1,3f +1: ld r9,8(r4) + std r8,8(r3) +2: ldu r8,16(r4) + stdu r9,16(r3) + bdnz 1b +3: std r8,8(r3) + beqlr + addi r3,r3,16 + ld r9,8(r4) +.Ldo_tail: + bf cr7*4+1,1f + rotldi r9,r9,32 + stw r9,0(r3) + addi r3,r3,4 +1: bf cr7*4+2,2f + rotldi r9,r9,16 + sth r9,0(r3) + addi r3,r3,2 +2: bf cr7*4+3,3f + rotldi r9,r9,8 + stb r9,0(r3) +3: blr + +.Lsrc_unaligned: + srdi r6,r5,3 + addi r5,r5,-16 + subf r4,r0,r4 + srdi r7,r5,4 + sldi r10,r0,3 + cmpdi cr6,r6,3 + andi. r5,r5,7 + mtctr r7 + subfic r11,r10,64 + add r5,r5,r0 + + bt cr7*4+0,0f + + ld r9,0(r4) # 3+2n loads, 2+2n stores + ld r0,8(r4) + sld r6,r9,r10 + ldu r9,16(r4) + srd r7,r0,r11 + sld r8,r0,r10 + or r7,r7,r6 + blt cr6,4f + ld r0,8(r4) + # s1<< in r8, d0=(s0<<|s1>>) in r7, s3 in r0, s2 in r9, nix in r6 & r12 + b 2f + +0: ld r0,0(r4) # 4+2n loads, 3+2n stores + ldu r9,8(r4) + sld r8,r0,r10 + addi r3,r3,-8 + blt cr6,5f + ld r0,8(r4) + srd r12,r9,r11 + sld r6,r9,r10 + ldu r9,16(r4) + or r12,r8,r12 + srd r7,r0,r11 + sld r8,r0,r10 + addi r3,r3,16 + beq cr6,3f + + # d0=(s0<<|s1>>) in r12, s1<< in r6, s2>> in r7, s2<< in r8, s3 in r9 +1: or r7,r7,r6 + ld r0,8(r4) + std r12,8(r3) +2: srd r12,r9,r11 + sld r6,r9,r10 + ldu r9,16(r4) + or r12,r8,r12 + stdu r7,16(r3) + srd r7,r0,r11 + sld r8,r0,r10 + bdnz 1b + +3: std r12,8(r3) + or r7,r7,r6 +4: std r7,16(r3) +5: srd r12,r9,r11 + or r12,r8,r12 + std r12,24(r3) + beqlr + cmpwi cr1,r5,8 + addi r3,r3,32 + sld r9,r9,r10 + blt cr1,.Ldo_tail + ld r0,8(r4) + srd r7,r0,r11 + or r9,r7,r9 + b .Ldo_tail + +.Ldst_unaligned: + mtcrf 0x01,r6 # put #bytes to 8B bdry into cr7 + subf r5,r6,r5 + li r7,0 + cmpldi r1,r5,16 + bf cr7*4+3,1f + lbz r0,0(r4) + stb r0,0(r3) + addi r7,r7,1 +1: bf cr7*4+2,2f + lhzx r0,r7,r4 + sthx r0,r7,r3 + addi r7,r7,2 +2: bf cr7*4+1,3f + lwzx r0,r7,r4 + stwx r0,r7,r3 +3: mtcrf 0x01,r5 + add r4,r6,r4 + add r3,r6,r3 + b .Ldst_aligned + +.Lshort_copy: + bf cr7*4+0,1f + lwz r0,0(r4) + lwz r9,4(r4) + addi r4,r4,8 + stw r0,0(r3) + stw r9,4(r3) + addi r3,r3,8 +1: bf cr7*4+1,2f + lwz r0,0(r4) + addi r4,r4,4 + stw r0,0(r3) + addi r3,r3,4 +2: bf cr7*4+2,3f + lhz r0,0(r4) + addi r4,r4,2 + sth r0,0(r3) + addi r3,r3,2 +3: bf cr7*4+3,4f + lbz r0,0(r4) + stb r0,0(r3) +4: blr diff -Nru a/arch/ppc64/lib/string.S b/arch/ppc64/lib/string.S --- a/arch/ppc64/lib/string.S Sun Jun 2 18:44:56 2002 +++ b/arch/ppc64/lib/string.S Sun Jun 2 18:44:56 2002 @@ -12,61 +12,6 @@ #include #include -#define CACHE_LINE_SIZE 128 -#define LG_CACHE_LINE_SIZE 7 -#define MAX_COPY_PREFETCH 1 - -#define COPY_16_BYTES \ - lwz r7,4(r4); \ - lwz r8,8(r4); \ - lwz r9,12(r4); \ - lwzu r10,16(r4); \ - stw r7,4(r6); \ - stw r8,8(r6); \ - stw r9,12(r6); \ - stwu r10,16(r6) - -#define COPY_16_BYTES_WITHEX(n) \ -8 ## n ## 0: \ - lwz r7,4(r4); \ -8 ## n ## 1: \ - lwz r8,8(r4); \ -8 ## n ## 2: \ - lwz r9,12(r4); \ -8 ## n ## 3: \ - lwzu r10,16(r4); \ -8 ## n ## 4: \ - stw r7,4(r6); \ -8 ## n ## 5: \ - stw r8,8(r6); \ -8 ## n ## 6: \ - stw r9,12(r6); \ -8 ## n ## 7: \ - stwu r10,16(r6) - -#define COPY_16_BYTES_EXCODE(n) \ -9 ## n ## 0: \ - addi r5,r5,-(16 * n); \ - b 104f; \ -9 ## n ## 1: \ - addi r5,r5,-(16 * n); \ - b 105f; \ -.section __ex_table,"a"; \ - .align 3; \ - .llong 8 ## n ## 0b,9 ## n ## 0b; \ - .llong 8 ## n ## 1b,9 ## n ## 0b; \ - .llong 8 ## n ## 2b,9 ## n ## 0b; \ - .llong 8 ## n ## 3b,9 ## n ## 0b; \ - .llong 8 ## n ## 4b,9 ## n ## 1b; \ - .llong 8 ## n ## 5b,9 ## n ## 1b; \ - .llong 8 ## n ## 6b,9 ## n ## 1b; \ - .llong 8 ## n ## 7b,9 ## n ## 1b; \ -.text - -CACHELINE_BYTES = CACHE_LINE_SIZE -LG_CACHELINE_BYTES = LG_CACHE_LINE_SIZE -CACHELINE_MASK = (CACHE_LINE_SIZE-1) - _GLOBAL(strcpy) addi r5,r3,-1 addi r4,r4,-1 @@ -148,48 +93,7 @@ _GLOBAL(memmove) cmplw 0,r3,r4 bgt .backwards_memcpy - /* fall through */ - -_GLOBAL(memcpy) - srwi. r7,r5,3 - addi r6,r3,-4 - addi r4,r4,-4 - beq 2f /* if less than 8 bytes to do */ - andi. r0,r6,3 /* get dest word aligned */ - mtctr r7 - bne 5f -1: lwz r7,4(r4) - lwzu r8,8(r4) - stw r7,4(r6) - stwu r8,8(r6) - bdnz 1b - andi. r5,r5,7 -2: cmplwi 0,r5,4 - blt 3f - lwzu r0,4(r4) - addi r5,r5,-4 - stwu r0,4(r6) -3: cmpwi 0,r5,0 - beqlr - mtctr r5 - addi r4,r4,3 - addi r6,r6,3 -4: lbzu r0,1(r4) - stbu r0,1(r6) - bdnz 4b - blr -5: subfic r0,r0,4 - mtctr r0 -6: lbz r7,4(r4) - addi r4,r4,1 - stb r7,4(r6) - addi r6,r6,1 - bdnz 6b - subf r5,r0,r5 - rlwinm. r7,r5,32-3,3,31 - beq 2b - mtctr r7 - b 1b + b .memcpy _GLOBAL(backwards_memcpy) rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ @@ -252,195 +156,6 @@ beqlr 2: li r3,0 blr - -_GLOBAL(__copy_tofrom_user) - addi r4,r4,-4 - addi r6,r3,-4 - neg r0,r3 - andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */ - beq 58f - - cmplw 0,r5,r0 /* is this more than total to do? */ - blt 63f /* if not much to do */ - andi. r8,r0,3 /* get it word-aligned first */ - mtctr r8 - beq+ 61f -70: lbz r9,4(r4) /* do some bytes */ -71: stb r9,4(r6) - addi r4,r4,1 - addi r6,r6,1 - bdnz 70b -61: subf r5,r0,r5 - srwi. r0,r0,2 - mtctr r0 - beq 58f -72: lwzu r9,4(r4) /* do some words */ -73: stwu r9,4(r6) - bdnz 72b - -58: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */ - clrlwi r5,r5,32-LG_CACHELINE_BYTES - li r11,4 - beq 63f - - /* Here we decide how far ahead to prefetch the source */ -#if MAX_COPY_PREFETCH > 1 - /* Heuristically, for large transfers we prefetch - MAX_COPY_PREFETCH cachelines ahead. For small transfers - we prefetch 1 cacheline ahead. */ - cmpwi r0,MAX_COPY_PREFETCH - li r7,1 - li r3,4 - ble 111f - li r7,MAX_COPY_PREFETCH -111: mtctr r7 -112: dcbt r3,r4 - addi r3,r3,CACHELINE_BYTES - bdnz 112b -#else /* MAX_COPY_PREFETCH == 1 */ - li r3,CACHELINE_BYTES + 4 - dcbt r11,r4 -#endif /* MAX_COPY_PREFETCH */ - - mtctr r0 -53: - dcbt r3,r4 - dcbz r11,r6 -/* had to move these to keep extable in order */ - .section __ex_table,"a" - .align 3 - .llong 70b,100f - .llong 71b,101f - .llong 72b,102f - .llong 73b,103f - .llong 53b,105f - .text -/* the main body of the cacheline loop */ - COPY_16_BYTES_WITHEX(0) -#if CACHE_LINE_SIZE >= 32 - COPY_16_BYTES_WITHEX(1) -#if CACHE_LINE_SIZE >= 64 - COPY_16_BYTES_WITHEX(2) - COPY_16_BYTES_WITHEX(3) -#if CACHE_LINE_SIZE >= 128 - COPY_16_BYTES_WITHEX(4) - COPY_16_BYTES_WITHEX(5) - COPY_16_BYTES_WITHEX(6) - COPY_16_BYTES_WITHEX(7) -#endif -#endif -#endif - bdnz 53b - -63: srwi. r0,r5,2 - mtctr r0 - beq 64f -30: lwzu r0,4(r4) -31: stwu r0,4(r6) - bdnz 30b - -64: andi. r0,r5,3 - mtctr r0 - beq+ 65f -40: lbz r0,4(r4) -41: stb r0,4(r6) - addi r4,r4,1 - addi r6,r6,1 - bdnz 40b -65: li r3,0 - blr - -/* read fault, initial single-byte copy */ -100: li r4,0 - b 90f -/* write fault, initial single-byte copy */ -101: li r4,1 -90: subf r5,r8,r5 - li r3,0 - b 99f -/* read fault, initial word copy */ -102: li r4,0 - b 91f -/* write fault, initial word copy */ -103: li r4,1 -91: li r3,2 - b 99f - -/* - * this stuff handles faults in the cacheline loop and branches to either - * 104f (if in read part) or 105f (if in write part), after updating r5 - */ - COPY_16_BYTES_EXCODE(0) -#if CACHE_LINE_SIZE >= 32 - COPY_16_BYTES_EXCODE(1) -#if CACHE_LINE_SIZE >= 64 - COPY_16_BYTES_EXCODE(2) - COPY_16_BYTES_EXCODE(3) -#if CACHE_LINE_SIZE >= 128 - COPY_16_BYTES_EXCODE(4) - COPY_16_BYTES_EXCODE(5) - COPY_16_BYTES_EXCODE(6) - COPY_16_BYTES_EXCODE(7) -#endif -#endif -#endif - -/* read fault in cacheline loop */ -104: li r4,0 - b 92f -/* fault on dcbz (effectively a write fault) */ -/* or write fault in cacheline loop */ -105: li r4,1 -92: li r3,LG_CACHELINE_BYTES - b 99f -/* read fault in final word loop */ -108: li r4,0 - b 93f -/* write fault in final word loop */ -109: li r4,1 -93: andi. r5,r5,3 - li r3,2 - b 99f -/* read fault in final byte loop */ -110: li r4,0 - b 94f -/* write fault in final byte loop */ -111: li r4,1 -94: li r5,0 - li r3,0 -/* - * At this stage the number of bytes not copied is - * r5 + (ctr << r3), and r4 is 0 for read or 1 for write. - */ -99: mfctr r0 - slw r3,r0,r3 - add r3,r3,r5 - cmpwi 0,r4,0 - bne 120f -/* for read fault, clear out the destination: r3 bytes starting at 4(r6) */ - srwi. r0,r3,2 - li r9,0 - mtctr r0 - beq 113f -112: stwu r9,4(r6) - bdnz 112b -113: andi. r0,r3,3 - mtctr r0 - beq 120f -114: stb r9,4(r6) - addi r6,r6,1 - bdnz 114b -120: blr - - .section __ex_table,"a" - .align 3 - .llong 30b,108b - .llong 31b,109b - .llong 40b,110b - .llong 41b,111b - .llong 112b,120b - .llong 114b,120b - .text _GLOBAL(__clear_user) addi r6,r3,-4 diff -Nru a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c --- a/arch/ppc64/mm/fault.c Sun Jun 2 18:44:56 2002 +++ b/arch/ppc64/mm/fault.c Sun Jun 2 18:44:56 2002 @@ -38,16 +38,11 @@ #include -#if defined(CONFIG_XMON) || defined(CONFIG_KGDB) -extern void (*debugger)(struct pt_regs *); -extern void (*debugger_fault_handler)(struct pt_regs *); -extern int (*debugger_dabr_match)(struct pt_regs *); +#ifdef CONFIG_DEBUG_KERNEL int debugger_kernel_faults = 1; #endif -extern void die_if_kernel(char *, struct pt_regs *, long); -void bad_page_fault(struct pt_regs *, unsigned long); -void do_page_fault(struct pt_regs *, unsigned long, unsigned long); +void bad_page_fault(struct pt_regs *, unsigned long, int); /* * For 600- and 800-family processors, the error_code parameter is DSISR @@ -71,7 +66,7 @@ if (regs->trap == 0x400) error_code &= 0x48200000; -#if defined(CONFIG_XMON) || defined(CONFIG_KGDB) +#ifdef CONFIG_DEBUG_KERNEL if (debugger_fault_handler && (regs->trap == 0x300 || regs->trap == 0x380)) { debugger_fault_handler(regs); @@ -83,10 +78,10 @@ if (debugger_dabr_match(regs)) return; } -#endif /* CONFIG_XMON || CONFIG_KGDB */ +#endif if (in_interrupt() || mm == NULL) { - bad_page_fault(regs, address); + bad_page_fault(regs, address, SIGSEGV); return; } down_read(&mm->mmap_sem); @@ -104,7 +99,7 @@ good_area: code = SEGV_ACCERR; - + /* a write */ if (is_write) { if (!(vma->vm_flags & VM_WRITE)) @@ -124,18 +119,18 @@ * make sure we exit gracefully rather than endlessly redo * the fault. */ - switch (handle_mm_fault(mm, vma, address, is_write)) { + switch (handle_mm_fault(mm, vma, address, is_write)) { - case 1: - current->min_flt++; - break; - case 2: - current->maj_flt++; - break; - case 0: - goto do_sigbus; - default: - goto out_of_memory; + case 1: + current->min_flt++; + break; + case 2: + current->maj_flt++; + break; + case 0: + goto do_sigbus; + default: + goto out_of_memory; } up_read(&mm->mmap_sem); @@ -143,7 +138,7 @@ bad_area: up_read(&mm->mmap_sem); - + /* User mode accesses cause a SIGSEGV */ if (user_mode(regs)) { info.si_signo = SIGSEGV; @@ -151,15 +146,15 @@ info.si_code = code; info.si_addr = (void *) address; #ifdef CONFIG_XMON - ifppcdebug(PPCDBG_SIGNALXMON) - PPCDBG_ENTER_DEBUGGER_REGS(regs); + ifppcdebug(PPCDBG_SIGNALXMON) + PPCDBG_ENTER_DEBUGGER_REGS(regs); #endif force_sig_info(SIGSEGV, &info, current); return; } - bad_page_fault(regs, address); + bad_page_fault(regs, address, SIGSEGV); return; /* @@ -176,7 +171,7 @@ printk("VM: killing process %s\n", current->comm); if (user_mode(regs)) do_exit(SIGKILL); - bad_page_fault(regs, address); + bad_page_fault(regs, address, SIGKILL); return; do_sigbus: @@ -187,7 +182,7 @@ info.si_addr = (void *)address; force_sig_info (SIGBUS, &info, current); if (!user_mode(regs)) - bad_page_fault(regs, address); + bad_page_fault(regs, address, SIGBUS); } /* @@ -196,8 +191,10 @@ * in traps.c. */ void -bad_page_fault(struct pt_regs *regs, unsigned long address) +bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) { + extern void die(const char *, struct pt_regs *, long); + unsigned long fixup; /* Are we prepared to handle this fault? */ @@ -207,13 +204,9 @@ } /* kernel has accessed a bad area */ - show_regs(regs); -#if defined(CONFIG_XMON) || defined(CONFIG_KGDB) +#ifdef CONFIG_DEBUG_KERNEL if (debugger_kernel_faults) debugger(regs); #endif - print_backtrace( (unsigned long *)regs->gpr[1] ); - panic("kernel access of bad area pc %lx lr %lx address %lX tsk %s/%d", - regs->nip,regs->link,address,current->comm,current->pid); + die("Kernel access of bad area", regs, sig); } - diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c Sun Jun 2 18:44:58 2002 +++ b/arch/ppc64/mm/init.c Sun Jun 2 18:44:58 2002 @@ -85,14 +85,10 @@ void mm_init_ppc64(void); -unsigned long *pmac_find_end_of_memory(void); -extern unsigned long *find_end_of_memory(void); - extern pgd_t ioremap_dir[]; pgd_t * ioremap_pgd = (pgd_t *)&ioremap_dir; static void map_io_page(unsigned long va, unsigned long pa, int flags); -extern void die_if_kernel(char *,struct pt_regs *,long); unsigned long klimit = (unsigned long)_end; @@ -246,20 +242,17 @@ void flush_tlb_mm(struct mm_struct *mm) { - if (mm->map_count) { - struct vm_area_struct *mp; - for (mp = mm->mmap; mp != NULL; mp = mp->vm_next) - __flush_tlb_range(mm, mp->vm_start, mp->vm_end); - } else { - /* MIKEC: It is not clear why this is needed */ - /* paulus: it is needed to clear out stale HPTEs - * when an address space (represented by an mm_struct) - * is being destroyed. */ - __flush_tlb_range(mm, USER_START, USER_END); - } + struct vm_area_struct *mp; + + spin_lock(&mm->page_table_lock); + + for (mp = mm->mmap; mp != NULL; mp = mp->vm_next) + __flush_tlb_range(mm, mp->vm_start, mp->vm_end); /* XXX are there races with checking cpu_vm_mask? - Anton */ mm->cpu_vm_mask = 0; + + spin_unlock(&mm->page_table_lock); } /* @@ -399,47 +392,40 @@ flush_hash_range(context, i, local); } - -void __init free_initmem(void) +void free_initmem(void) { - unsigned long a; - unsigned long num_freed_pages = 0; -#define FREESEC(START,END,CNT) do { \ - a = (unsigned long)(&START); \ - for (; a < (unsigned long)(&END); a += PAGE_SIZE) { \ - clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); \ - set_page_count(mem_map+MAP_NR(a), 1); \ - free_page(a); \ - CNT++; \ - } \ -} while (0) - - FREESEC(__init_begin,__init_end,num_freed_pages); + unsigned long addr; - printk ("Freeing unused kernel memory: %ldk init\n", - PGTOKB(num_freed_pages)); + addr = (unsigned long)(&__init_begin); + for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { + ClearPageReserved(virt_to_page(addr)); + set_page_count(virt_to_page(addr), 1); + free_page(addr); + totalram_pages++; + } + printk ("Freeing unused kernel memory: %dk freed\n", + (&__init_end - &__init_begin) >> 10); } #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { - unsigned long xstart = start; + if (start < end) + printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(start)); - set_page_count(mem_map+MAP_NR(start), 1); + ClearPageReserved(virt_to_page(start)); + set_page_count(virt_to_page(start), 1); free_page(start); totalram_pages++; } - printk ("Freeing initrd memory: %ldk freed\n", (end - xstart) >> 10); } #endif - - /* * Do very early mm setup. */ -void __init mm_init_ppc64(void) { +void __init mm_init_ppc64(void) +{ struct paca_struct *lpaca; unsigned long guard_page, index; @@ -467,8 +453,6 @@ ppc_md.progress("MM:exit", 0x211); } - - /* * Initialize the bootmem system and give it all the memory we * have available. @@ -582,11 +566,11 @@ for (addr = (unsigned long)sysmap; addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ; addr += PAGE_SIZE) - SetPageReserved(mem_map + MAP_NR(addr)); + SetPageReserved(virt_to_page(addr)); for (addr = KERNELBASE; addr <= (unsigned long)__va(lmb_end_of_DRAM()); addr += PAGE_SIZE) { - if (!PageReserved(mem_map + MAP_NR(addr))) + if (!PageReserved(virt_to_page(addr))) continue; if (addr < (ulong) etext) codepages++; @@ -665,6 +649,8 @@ * fault has been handled by updating a PTE in the linux page tables. * We use it to preload an HPTE into the hash table corresponding to * the updated linux PTE. + * + * This must always be called with the mm->page_table_lock held */ void update_mmu_cache(struct vm_area_struct *vma, unsigned long ea, pte_t pte) diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c --- a/arch/ppc64/xmon/xmon.c Sun Jun 2 18:44:57 2002 +++ b/arch/ppc64/xmon/xmon.c Sun Jun 2 18:44:57 2002 @@ -309,7 +309,6 @@ std 29,232(%0)\n\ std 30,240(%0)\n\ std 31,248(%0)" : : "b" (®s)); - printf("xmon called\n"); /* Fetch the link reg for this stack frame. NOTE: the prev printf fills in the lr. */ regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2]; diff -Nru a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c --- a/arch/s390/kernel/debug.c Sun Jun 2 18:44:56 2002 +++ b/arch/s390/kernel/debug.c Sun Jun 2 18:44:56 2002 @@ -424,7 +424,6 @@ { size_t count = 0; size_t entry_offset, size = 0; - int rc; file_private_info_t *p_info; p_info = ((file_private_info_t *) file->private_data); @@ -440,9 +439,9 @@ size = MIN((len - count), (size - entry_offset)); if(size){ - if ((rc = copy_to_user(user_buf + count, - p_info->temp_buf + entry_offset, size))) - return rc; + if (copy_to_user(user_buf + count, + p_info->temp_buf + entry_offset, size)) + return -EFAULT; } count += size; entry_offset = 0; diff -Nru a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c --- a/arch/s390/kernel/ptrace.c Sun Jun 2 18:44:57 2002 +++ b/arch/s390/kernel/ptrace.c Sun Jun 2 18:44:57 2002 @@ -116,14 +116,14 @@ { if(writeuser) { - retval=copy_from_user((void *)realuseraddr,(void *)copyaddr,len); + retval=copy_from_user((void *)realuseraddr,(void *)copyaddr,len) ? -EFAULT : 0; } else { if(realuseraddr==(addr_t)NULL) - retval=(clear_user((void *)copyaddr,len)==-EFAULT ? -EIO:0); + retval=(clear_user((void *)copyaddr,len) ? -EIO:0); else - retval=(copy_to_user((void *)copyaddr,(void *)realuseraddr,len)==-EFAULT ? -EIO:0); + retval=(copy_to_user((void *)copyaddr,(void *)realuseraddr,len) ? -EIO:0); } } else diff -Nru a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c --- a/arch/s390/kernel/signal.c Sun Jun 2 18:44:56 2002 +++ b/arch/s390/kernel/signal.c Sun Jun 2 18:44:56 2002 @@ -141,7 +141,7 @@ - +/* Returns non-zero on fault. */ static int save_sigregs(struct pt_regs *regs,_sigregs *sregs) { int err; @@ -157,6 +157,7 @@ } +/* Returns positive number on error */ static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs) { int err; diff -Nru a/arch/s390/math-emu/math.c b/arch/s390/math-emu/math.c --- a/arch/s390/math-emu/math.c Sun Jun 2 18:44:57 2002 +++ b/arch/s390/math-emu/math.c Sun Jun 2 18:44:57 2002 @@ -86,13 +86,13 @@ #define mathemu_copy_from_user(d, s, n)\ do { \ - if (copy_from_user((d),(s),(n)) == -EFAULT) \ + if (copy_from_user((d),(s),(n)) != 0) \ return SIGSEGV; \ } while (0) #define mathemu_copy_to_user(d, s, n) \ do { \ - if (copy_to_user((d),(s),(n)) == -EFAULT) \ + if (copy_to_user((d),(s),(n)) != 0) \ return SIGSEGV; \ } while (0) diff -Nru a/arch/s390x/kernel/debug.c b/arch/s390x/kernel/debug.c --- a/arch/s390x/kernel/debug.c Sun Jun 2 18:44:56 2002 +++ b/arch/s390x/kernel/debug.c Sun Jun 2 18:44:56 2002 @@ -427,7 +427,6 @@ { size_t count = 0; size_t entry_offset, size = 0; - int rc; file_private_info_t *p_info; p_info = ((file_private_info_t *) file->private_data); @@ -443,9 +442,9 @@ size = MIN((len - count), (size - entry_offset)); if(size){ - if ((rc = copy_to_user(user_buf + count, - p_info->temp_buf + entry_offset, size))) - return rc; + if (copy_to_user(user_buf + count, + p_info->temp_buf + entry_offset, size)) + return -EFAULT; } count += size; entry_offset = 0; diff -Nru a/arch/s390x/kernel/ptrace.c b/arch/s390x/kernel/ptrace.c --- a/arch/s390x/kernel/ptrace.c Sun Jun 2 18:44:56 2002 +++ b/arch/s390x/kernel/ptrace.c Sun Jun 2 18:44:56 2002 @@ -122,7 +122,7 @@ retval = clear_user(copyptr, len); else retval = copy_to_user(copyptr,realuserptr,len); - retval = (retval == -EFAULT) ? -EIO : 0; + retval = retval ? -EIO : 0; } } else { if (writeuser) diff -Nru a/arch/s390x/kernel/signal.c b/arch/s390x/kernel/signal.c --- a/arch/s390x/kernel/signal.c Sun Jun 2 18:44:56 2002 +++ b/arch/s390x/kernel/signal.c Sun Jun 2 18:44:56 2002 @@ -141,7 +141,7 @@ - +/* Returns non-zero on fault */ static int save_sigregs(struct pt_regs *regs,_sigregs *sregs) { int err; @@ -157,6 +157,7 @@ } +/* Returns positive number on error */ static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs) { int err; diff -Nru a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c --- a/arch/sparc/kernel/sys_sunos.c Sun Jun 2 18:44:57 2002 +++ b/arch/sparc/kernel/sys_sunos.c Sun Jun 2 18:44:57 2002 @@ -487,7 +487,7 @@ ret |= __copy_to_user(&name->mach[0], &system_utsname.machine[0], sizeof(name->mach) - 1); } up_read(&uts_sem); - return ret; + return ret ? -EFAULT : 0; } asmlinkage int sunos_nosys(void) diff -Nru a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c --- a/arch/sparc64/kernel/sys_sparc.c Sun Jun 2 18:44:57 2002 +++ b/arch/sparc64/kernel/sys_sparc.c Sun Jun 2 18:44:57 2002 @@ -252,7 +252,7 @@ int ret = sys_newuname(name); if (current->personality == PER_LINUX32 && !ret) { - ret = copy_to_user(name->machine, "sparc\0\0", 8); + ret = copy_to_user(name->machine, "sparc\0\0", 8) ? -EFAULT : 0; } return ret; } diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c --- a/drivers/acorn/block/mfmhd.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acorn/block/mfmhd.c Sun Jun 2 18:44:56 2002 @@ -570,7 +570,7 @@ DBG("mfm_rw_intr: returned from cont->done\n"); } else { /* Its going to generate another interrupt */ - SET_INTR(mfm_rw_intr); + DEVICE_INTR = mfm_rw_intr; }; } @@ -578,7 +578,7 @@ { DBG("setting up for rw...\n"); - SET_INTR(mfm_rw_intr); + DEVICE_INTR = mfm_rw_intr; issue_command(raw_cmd.cmdcode, raw_cmd.cmddata, raw_cmd.cmdlen); } @@ -608,7 +608,7 @@ /* Command end without seek end (see data sheet p.20) for parallel seek - we have to send a POL command to wait for the seek */ if (mfm_status & STAT_CED) { - SET_INTR(mfm_recal_intr); + DEVICE_INTR = mfm_recal_intr; issue_command(CMD_POL, NULL, 0); return; } @@ -638,7 +638,7 @@ return; } if (mfm_status & STAT_CED) { - SET_INTR(mfm_seek_intr); + DEVICE_INTR = mfm_seek_intr; issue_command(CMD_POL, NULL, 0); return; } @@ -696,7 +696,7 @@ DBG("seeking...\n"); if (MFM_DRV_INFO.cylinder < 0) { - SET_INTR(mfm_recal_intr); + DEVICE_INTR = mfm_recal_intr; DBG("mfm_seek: about to call specify\n"); mfm_specify (); /* DAG added this */ @@ -712,7 +712,7 @@ cmdb[2] = raw_cmd.cylinder >> 8; cmdb[3] = raw_cmd.cylinder; - SET_INTR(mfm_seek_intr); + DEVICE_INTR = mfm_seek_intr; issue_command(CMD_SEK, cmdb, 4); } else mfm_setup_rw(); @@ -907,7 +907,7 @@ if (blk_queue_empty(QUEUE)) { printk("mfm_request: Exiting due to empty queue (pre)\n"); - CLEAR_INTR; + DEVICE_INTR = NULL; Busy = 0; return; } @@ -971,7 +971,7 @@ { void (*handler) (void) = DEVICE_INTR; - CLEAR_INTR; + DEVICE_INTR = NULL; DBG("mfm_interrupt_handler (handler=0x%p)\n", handler); diff -Nru a/drivers/acpi/Config.help b/drivers/acpi/Config.help --- a/drivers/acpi/Config.help Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/Config.help Sun Jun 2 18:44:57 2002 @@ -12,6 +12,12 @@ Management (APM) specification. If both ACPI and APM support are configured, whichever is loaded first shall be used. + Add "acpi=off" to the kernel command line to disable this feature. + (Try "man bootparam" or see the documentation of your boot loader + about how to pass options to the kernel at boot time.) + + ---------- + The ACPI SourceForge project contains the latest source code, documentation, tools, mailing list subscription, and other information. This project is available at: @@ -26,51 +32,28 @@ available at: -CONFIG_ACPI_BOOT - This option enables the use of ACPI tables for obtaining various - boot-time configuration information such as system processors, - memory, and interrupt routing. - - ACPI tables supercede legacy BIOS interfaces. For example, the - Multiple APIC Description Table (MADT) defined by the ACPI - Specification is a replacement for the MP Configuration Table - defined by the MultiProcessor Specification (MPS). - - You can disable this feature on IA32 systems by adding "acpi_boot=off" - to your kernel command line. (Try "man bootparam" or see the - documentation of your boot loader about how to pass options to the - kernel at boot time.) - - IA64 systems do not support legacy BIOS interfaces and thus rely - on ACPI tables to boot the system. No kernel command line options - are supported. - -CONFIG_ACPI_INTERPRETER - The ACPI Interpreter (a.k.a. ACPI Core Subsystem) provides the - fundamental services required to parse the ACPI namespace, evaluate - control methods, and manage ACPI hardware and events. This - subsystem exposes kernel interfaces allowing higher level software - to manipulate ACPI defined hardware and software interfaces. +CONFIG_ACPI_HT_ONLY + This option enables limited ACPI support -- just enough to + enumerate processors from the ACPI Multiple APIC Description + Table (MADT). Note that ACPI supports both logical (e.g. Hyper- + Threading) and physical processors, where the MultiProcessor + Specification (MPS) table only supports physical processors. - Add "acpi=off" to the kernel command line to disable this feature. - (Try "man bootparam" or see the documentation of your boot loader - about how to pass options to the kernel at boot time.) - - Note that this option will enlarge your kernel by about 100K. + Full ACPI support (CONFIG_ACPI) is preferred. Use this option + only if you wish to limit ACPI's role to processor enumeration. -CONFIG_ACPI_BUS - The ACPI Bus driver enumerates and manages devices in the ACPI - namespace in a manner similar to other bus drivers (e.g. PCI). - All ACPI device drivers rely on its services. + There is no command-line option to disable this, but the kernel + will fall back to the MPS table if the MADT is not present. CONFIG_ACPI_AC This driver adds support for the AC Adapter object, which indicates - whether a system is on AC, or not. Typically, only laptops have - this object, since desktops are always on AC. + whether a system is on AC, or not. Typically, only mobile systems + have this object, since desktops are always on AC. CONFIG_ACPI_BATTERY This driver adds support for battery information through - /proc/acpi/battery. If you have a laptop with a battery, say Y. + /proc/acpi/battery. If you have a mobile system with a battery, + say Y. CONFIG_ACPI_BUTTON This driver registers for events based on buttons, such as the @@ -79,21 +62,10 @@ down the system. Until then, you can cat it, and see output when a button is pressed. -CONFIG_ACPI_DEBUG - The ACPI driver can optionally report errors with a great deal - of verbosity. Saying Y enables these statements. This will increase - your kernel size by around 50K. - CONFIG_ACPI_EC This driver is required on some systems for the proper operation of - the battery and thermal drivers. If you are compiling for a laptop, - say Y. - -CONFIG_ACPI_PCI - This option enables ACPI-based enumeration and configuration of PCI - root bridge devices, including PCI interrupt routing (_PRT) support. - This is required on platforms that no longer support legacy tables - (e.g. MPS/PIR) or have erroneous table entries. + the battery and thermal drivers. If you are compiling for a + mobile system, say Y. CONFIG_ACPI_PROCESSOR This driver installs ACPI as the idle handler for Linux, and uses @@ -114,9 +86,8 @@ This driver will enable your system to shut down using ACPI, and dump your ACPI DSDT table using /proc/acpi/dsdt. -CONFIG_ACPI_SLEEP - Enables low-level sleep support, allowing the platform to enter - and exit the S1-S4 states. Note that although the platform may - support this capability, full sleep support will not be viable - until drivers properly save/restore hardware context. (In other - words, use at your own risk!) +CONFIG_ACPI_DEBUG + The ACPI driver can optionally report errors with a great deal + of verbosity. Saying Y enables these statements. This will increase + your kernel size by around 50K. + diff -Nru a/drivers/acpi/Config.in b/drivers/acpi/Config.in --- a/drivers/acpi/Config.in Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/Config.in Sun Jun 2 18:44:58 2002 @@ -1,40 +1,76 @@ # # ACPI Configuration # + if [ "$CONFIG_X86" = "y" ]; then + mainmenu_option next_comment comment 'ACPI Support' - dep_bool 'ACPI Support' CONFIG_ACPI $CONFIG_PCI + bool 'ACPI Support' CONFIG_ACPI if [ "$CONFIG_ACPI" = "y" ]; then - define_bool CONFIG_ACPI_BOOT y - define_bool CONFIG_ACPI_BUS y - define_bool CONFIG_ACPI_EC y - define_bool CONFIG_ACPI_INTERPRETER y - define_bool CONFIG_ACPI_PCI y - define_bool CONFIG_ACPI_POWER y - define_bool CONFIG_ACPI_SLEEP y - define_bool CONFIG_ACPI_SYSTEM y - tristate ' AC Adapter' CONFIG_ACPI_AC - tristate ' Battery' CONFIG_ACPI_BATTERY - tristate ' Button' CONFIG_ACPI_BUTTON - tristate ' Fan' CONFIG_ACPI_FAN - tristate ' Processor' CONFIG_ACPI_PROCESSOR - dep_tristate ' Thermal Zone' CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR - bool ' Debug Statements' CONFIG_ACPI_DEBUG + if [ "$CONFIG_X86_LOCAL_APIC" = "y" ]; then + bool 'CPU Enumeration Only' CONFIG_ACPI_HT_ONLY + fi + + if [ "$CONFIG_ACPI_HT_ONLY" = "y" ]; then + define_bool CONFIG_ACPI_BOOT y + else + define_bool CONFIG_ACPI_BOOT y + define_bool CONFIG_ACPI_BUS y + define_bool CONFIG_ACPI_INTERPRETER y + define_bool CONFIG_ACPI_EC y + define_bool CONFIG_ACPI_POWER y + if [ "$CONFIG_PCI" = "y" ]; then + define_bool CONFIG_ACPI_PCI y + fi + define_bool CONFIG_ACPI_SLEEP y + define_bool CONFIG_ACPI_SYSTEM y + tristate ' AC Adapter' CONFIG_ACPI_AC + tristate ' Battery' CONFIG_ACPI_BATTERY + tristate ' Button' CONFIG_ACPI_BUTTON + tristate ' Fan' CONFIG_ACPI_FAN + tristate ' Processor' CONFIG_ACPI_PROCESSOR + dep_tristate ' Thermal Zone' CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR + bool ' Debug Statements' CONFIG_ACPI_DEBUG + fi fi + endmenu + fi + if [ "$CONFIG_IA64" = "y" ]; then + + if [ "$CONFIG_IA64_SGI_SN" = "y" ]; then + mainmenu_option next_comment + comment 'ACPI Support' + define_bool CONFIG_ACPI y + define_bool CONFIG_ACPI_EFI y + define_bool CONFIG_ACPI_BOOT y + define_bool CONFIG_ACPI_BUS n + define_bool CONFIG_ACPI_INTERPRETER n + define_bool CONFIG_ACPI_PCI n + define_bool CONFIG_ACPI_POWER n + define_bool CONFIG_ACPI_SYSTEM n + define_bool CONFIG_ACPI_BUTTON n + define_bool CONFIG_ACPI_FAN n + define_bool CONFIG_ACPI_PROCESSOR n + define_bool CONFIG_ACPI_THERMAL n + endmenu + fi + if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then mainmenu_option next_comment comment 'ACPI Support' + if [ "$CONFIG_PCI" = "y" ]; then + define_bool CONFIG_ACPI_PCI y + fi define_bool CONFIG_ACPI y define_bool CONFIG_ACPI_EFI y define_bool CONFIG_ACPI_BOOT y define_bool CONFIG_ACPI_BUS y define_bool CONFIG_ACPI_INTERPRETER y - define_bool CONFIG_ACPI_PCI y define_bool CONFIG_ACPI_POWER y define_bool CONFIG_ACPI_SYSTEM y tristate ' Button' CONFIG_ACPI_BUTTON @@ -44,4 +80,5 @@ bool ' Debug Statements' CONFIG_ACPI_DEBUG endmenu fi + fi diff -Nru a/drivers/acpi/Makefile b/drivers/acpi/Makefile --- a/drivers/acpi/Makefile Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/Makefile Sun Jun 2 18:44:57 2002 @@ -19,12 +19,12 @@ # # ACPI Boot-Time Table Parsing # -obj-$(CONFIG_ACPI_BOOT) += acpi_tables.o +obj-$(CONFIG_ACPI_BOOT) += tables.o # # ACPI Core Subsystem (Interpreter) # -obj-$(CONFIG_ACPI_INTERPRETER) += acpi_osl.o acpi_utils.o \ +obj-$(CONFIG_ACPI_INTERPRETER) += osl.o utils.o \ dispatcher/ events/ executer/ hardware/ \ namespace/ parser/ resources/ tables/ \ utilities/ @@ -32,16 +32,16 @@ # # ACPI Bus and Device Drivers # -obj-$(CONFIG_ACPI_BUS) += acpi_bus.o -obj-$(CONFIG_ACPI_AC) += acpi_ac.o -obj-$(CONFIG_ACPI_BATTERY) += acpi_battery.o -obj-$(CONFIG_ACPI_BUTTON) += acpi_button.o -obj-$(CONFIG_ACPI_EC) += acpi_ec.o -obj-$(CONFIG_ACPI_FAN) += acpi_fan.o -obj-$(CONFIG_ACPI_PCI) += acpi_pci_root.o acpi_pci_link.o -obj-$(CONFIG_ACPI_POWER) += acpi_power.o -obj-$(CONFIG_ACPI_PROCESSOR) += acpi_processor.o -obj-$(CONFIG_ACPI_THERMAL) += acpi_thermal.o -obj-$(CONFIG_ACPI_SYSTEM) += acpi_system.o +obj-$(CONFIG_ACPI_BUS) += bus.o +obj-$(CONFIG_ACPI_AC) += ac.o +obj-$(CONFIG_ACPI_BATTERY) += battery.o +obj-$(CONFIG_ACPI_BUTTON) += button.o +obj-$(CONFIG_ACPI_EC) += ec.o +obj-$(CONFIG_ACPI_FAN) += fan.o +obj-$(CONFIG_ACPI_PCI) += pci_root.o pci_link.o pci_irq.o pci_bind.o +obj-$(CONFIG_ACPI_POWER) += power.o +obj-$(CONFIG_ACPI_PROCESSOR) += processor.o +obj-$(CONFIG_ACPI_THERMAL) += thermal.o +obj-$(CONFIG_ACPI_SYSTEM) += system.o include $(TOPDIR)/Rules.make diff -Nru a/drivers/acpi/ac.c b/drivers/acpi/ac.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/ac.c Sun Jun 2 18:44:57 2002 @@ -0,0 +1,351 @@ +/* + * acpi_ac.c - ACPI AC Adapter Driver ($Revision: 26 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_AC_COMPONENT +ACPI_MODULE_NAME ("acpi_ac") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + + +int acpi_ac_add (struct acpi_device *device); +int acpi_ac_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_ac_driver = { + name: ACPI_AC_DRIVER_NAME, + class: ACPI_AC_CLASS, + ids: ACPI_AC_HID, + ops: { + add: acpi_ac_add, + remove: acpi_ac_remove, + }, +}; + +struct acpi_ac { + acpi_handle handle; + unsigned long state; +}; + + +/* -------------------------------------------------------------------------- + AC Adapter Management + -------------------------------------------------------------------------- */ + +static int +acpi_ac_get_state ( + struct acpi_ac *ac) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_ac_get_state"); + + if (!ac) + return_VALUE(-EINVAL); + + status = acpi_evaluate_integer(ac->handle, "_PSR", NULL, &ac->state); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error reading AC Adapter state\n")); + ac->state = ACPI_AC_STATUS_UNKNOWN; + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +struct proc_dir_entry *acpi_ac_dir = NULL; + +static int +acpi_ac_read_state ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_ac *ac = (struct acpi_ac *) data; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_ac_read_state"); + + if (!ac || (off != 0)) + goto end; + + if (acpi_ac_get_state(ac)) { + p += sprintf(p, "ERROR: Unable to read AC Adapter state\n"); + goto end; + } + + p += sprintf(p, "state: "); + switch (ac->state) { + case ACPI_AC_STATUS_OFFLINE: + p += sprintf(p, "off-line\n"); + break; + case ACPI_AC_STATUS_ONLINE: + p += sprintf(p, "on-line\n"); + break; + default: + p += sprintf(p, "unknown\n"); + break; + } + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_ac_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_ac_add_fs"); + + if (!acpi_ac_dir) { + acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir); + if (!acpi_ac_dir) + return_VALUE(-ENODEV); + } + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_ac_dir); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + } + + /* 'state' [R] */ + entry = create_proc_entry(ACPI_AC_FILE_STATE, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_AC_FILE_STATE)); + else { + entry->read_proc = acpi_ac_read_state; + entry->data = acpi_driver_data(device); + } + + return_VALUE(0); +} + + +static int +acpi_ac_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_ac_remove_fs"); + + if (!acpi_ac_dir) + return_VALUE(-ENODEV); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Model + -------------------------------------------------------------------------- */ + +void +acpi_ac_notify ( + acpi_handle handle, + u32 event, + void *data) +{ + struct acpi_ac *ac = (struct acpi_ac *) data; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_ac_notify"); + + if (!ac) + return; + + if (acpi_bus_get_device(ac->handle, &device)) + return_VOID; + + switch (event) { + case ACPI_AC_NOTIFY_STATUS: + acpi_ac_get_state(ac); + acpi_bus_generate_event(device, event, (u32) ac->state); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return_VOID; +} + + +int +acpi_ac_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_ac *ac = NULL; + + ACPI_FUNCTION_TRACE("acpi_ac_add"); + + if (!device) + return_VALUE(-EINVAL); + + ac = kmalloc(sizeof(struct acpi_ac), GFP_KERNEL); + if (!ac) + return_VALUE(-ENOMEM); + memset(ac, 0, sizeof(struct acpi_ac)); + + ac->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_AC_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_AC_CLASS); + acpi_driver_data(device) = ac; + + result = acpi_ac_get_state(ac); + if (result) + goto end; + + result = acpi_ac_add_fs(device); + if (result) + goto end; + + status = acpi_install_notify_handler(ac->handle, + ACPI_DEVICE_NOTIFY, acpi_ac_notify, ac); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing notify handler\n")); + result = -ENODEV; + goto end; + } + + printk(KERN_INFO PREFIX "%s [%s] (%s)\n", + acpi_device_name(device), acpi_device_bid(device), + ac->state?"on-line":"off-line"); + +end: + if (result) { + acpi_ac_remove_fs(device); + kfree(ac); + } + + return_VALUE(result); +} + + +int +acpi_ac_remove ( + struct acpi_device *device, + int type) +{ + acpi_status status = AE_OK; + struct acpi_ac *ac = NULL; + + ACPI_FUNCTION_TRACE("acpi_ac_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + ac = (struct acpi_ac *) acpi_driver_data(device); + + status = acpi_remove_notify_handler(ac->handle, + ACPI_DEVICE_NOTIFY, acpi_ac_notify); + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + + acpi_ac_remove_fs(device); + + kfree(ac); + + return_VALUE(0); +} + + +int __init +acpi_ac_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_ac_init"); + + result = acpi_bus_register_driver(&acpi_ac_driver); + if (result < 0) { + remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +void __exit +acpi_ac_exit (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_ac_exit"); + + result = acpi_bus_unregister_driver(&acpi_ac_driver); + if (!result) + remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); + + return_VOID; +} + + +module_init(acpi_ac_init); +module_exit(acpi_ac_exit); diff -Nru a/drivers/acpi/acpi_ac.c b/drivers/acpi/acpi_ac.c --- a/drivers/acpi/acpi_ac.c Sun Jun 2 18:44:57 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,352 +0,0 @@ -/* - * acpi_ac.c - ACPI AC Adapter Driver ($Revision: 23 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include "acpi_bus.h" -#include "acpi_drivers.h" - - -#define _COMPONENT ACPI_AC_COMPONENT -ACPI_MODULE_NAME ("acpi_ac") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME); -MODULE_LICENSE("GPL"); - -#define PREFIX "ACPI: " - - -int acpi_ac_add (struct acpi_device *device); -int acpi_ac_remove (struct acpi_device *device, int type); - -static struct acpi_driver acpi_ac_driver = { - name: ACPI_AC_DRIVER_NAME, - class: ACPI_AC_CLASS, - ids: ACPI_AC_HID, - ops: { - add: acpi_ac_add, - remove: acpi_ac_remove, - }, -}; - -struct acpi_ac { - acpi_handle handle; - unsigned long state; -}; - - -/* -------------------------------------------------------------------------- - AC Adapter Management - -------------------------------------------------------------------------- */ - -static int -acpi_ac_get_state ( - struct acpi_ac *ac) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE("acpi_ac_get_state"); - - if (!ac) - return_VALUE(-EINVAL); - - status = acpi_evaluate_integer(ac->handle, "_PSR", NULL, &ac->state); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error reading AC Adapter state\n")); - ac->state = ACPI_AC_STATUS_UNKNOWN; - return_VALUE(-ENODEV); - } - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -#include -#include - -struct proc_dir_entry *acpi_ac_dir = NULL; - -static int -acpi_ac_read_state ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_ac *ac = (struct acpi_ac *) data; - char *p = page; - int len = 0; - - ACPI_FUNCTION_TRACE("acpi_ac_read_state"); - - if (!ac || (off != 0)) - goto end; - - if (0 != acpi_ac_get_state(ac)) { - p += sprintf(p, "ERROR: Unable to read AC Adapter state\n"); - goto end; - } - - p += sprintf(p, "state: "); - switch (ac->state) { - case ACPI_AC_STATUS_OFFLINE: - p += sprintf(p, "off-line\n"); - break; - case ACPI_AC_STATUS_ONLINE: - p += sprintf(p, "on-line\n"); - break; - default: - p += sprintf(p, "unknown\n"); - break; - } - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_ac_add_fs ( - struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - - ACPI_FUNCTION_TRACE("acpi_ac_add_fs"); - - if (!acpi_ac_dir) { - acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir); - if (!acpi_ac_dir) - return_VALUE(-ENODEV); - } - - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_ac_dir); - if (!acpi_device_dir(device)) - return_VALUE(-ENODEV); - } - - /* 'state' [R] */ - entry = create_proc_entry(ACPI_AC_FILE_STATE, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_AC_FILE_STATE)); - else { - entry->read_proc = acpi_ac_read_state; - entry->data = acpi_driver_data(device); - } - - return_VALUE(0); -} - - -static int -acpi_ac_remove_fs ( - struct acpi_device *device) -{ - ACPI_FUNCTION_TRACE("acpi_ac_remove_fs"); - - if (!acpi_ac_dir) - return_VALUE(-ENODEV); - - if (acpi_device_dir(device)) - remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Driver Model - -------------------------------------------------------------------------- */ - -void -acpi_ac_notify ( - acpi_handle handle, - u32 event, - void *data) -{ - struct acpi_ac *ac = (struct acpi_ac *) data; - struct acpi_device *device = NULL; - - ACPI_FUNCTION_TRACE("acpi_ac_notify"); - - if (!ac) - return; - - if (0 != acpi_bus_get_device(ac->handle, &device)) - return_VOID; - - switch (event) { - case ACPI_AC_NOTIFY_STATUS: - acpi_ac_get_state(ac); - acpi_bus_generate_event(device, event, (u32) ac->state); - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Unsupported event [0x%x]\n", event)); - break; - } - - return_VOID; -} - - -int -acpi_ac_add ( - struct acpi_device *device) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_ac *ac = NULL; - - ACPI_FUNCTION_TRACE("acpi_ac_add"); - - if (!device) - return_VALUE(-EINVAL); - - ac = kmalloc(sizeof(struct acpi_ac), GFP_KERNEL); - if (!ac) - return_VALUE(-ENOMEM); - memset(ac, 0, sizeof(struct acpi_ac)); - - ac->handle = device->handle; - sprintf(acpi_device_name(device), "%s", ACPI_AC_DEVICE_NAME); - sprintf(acpi_device_class(device), "%s", ACPI_AC_CLASS); - acpi_driver_data(device) = ac; - - result = acpi_ac_get_state(ac); - if (0 != result) - goto end; - - result = acpi_ac_add_fs(device); - if (0 != result) - goto end; - - status = acpi_install_notify_handler(ac->handle, - ACPI_DEVICE_NOTIFY, acpi_ac_notify, ac); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error installing notify handler\n")); - result = -ENODEV; - goto end; - } - - printk(KERN_INFO PREFIX "%s [%s] (%s)\n", - acpi_device_name(device), acpi_device_bid(device), - ac->state?"on-line":"off-line"); - -end: - if (0 != result) { - acpi_ac_remove_fs(device); - kfree(ac); - } - - return_VALUE(result); -} - - -int -acpi_ac_remove ( - struct acpi_device *device, - int type) -{ - acpi_status status = AE_OK; - struct acpi_ac *ac = NULL; - - ACPI_FUNCTION_TRACE("acpi_ac_remove"); - - if (!device || !acpi_driver_data(device)) - return_VALUE(-EINVAL); - - ac = (struct acpi_ac *) acpi_driver_data(device); - - status = acpi_remove_notify_handler(ac->handle, - ACPI_DEVICE_NOTIFY, acpi_ac_notify); - if (ACPI_FAILURE(status)) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error removing notify handler\n")); - - acpi_ac_remove_fs(device); - - kfree(ac); - - return_VALUE(0); -} - - -int __init -acpi_ac_init (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_ac_init"); - - result = acpi_bus_register_driver(&acpi_ac_driver); - if (0 > result) { - remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); - return_VALUE(-ENODEV); - } - - return_VALUE(0); -} - - -void __exit -acpi_ac_exit (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_ac_exit"); - - result = acpi_bus_unregister_driver(&acpi_ac_driver); - if (0 == result) - remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); - - return_VOID; -} - - -module_init(acpi_ac_init); -module_exit(acpi_ac_exit); diff -Nru a/drivers/acpi/acpi_battery.c b/drivers/acpi/acpi_battery.c --- a/drivers/acpi/acpi_battery.c Sun Jun 2 18:44:56 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,831 +0,0 @@ -/* - * acpi_battery.c - ACPI Battery Driver ($Revision: 32 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include "acpi_bus.h" -#include "acpi_drivers.h" - - -#define _COMPONENT ACPI_BATTERY_COMPONENT -ACPI_MODULE_NAME ("acpi_battery") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME); -MODULE_LICENSE("GPL"); - -#define PREFIX "ACPI: " - - -#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF - -#define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS" -#define ACPI_BATTERY_FORMAT_BST "NNNN" - -static int acpi_battery_add (struct acpi_device *device); -static int acpi_battery_remove (struct acpi_device *device, int type); - -static struct acpi_driver acpi_battery_driver = { - name: ACPI_BATTERY_DRIVER_NAME, - class: ACPI_BATTERY_CLASS, - ids: ACPI_BATTERY_HID, - ops: { - add: acpi_battery_add, - remove: acpi_battery_remove, - }, -}; - -struct acpi_battery_status { - acpi_integer state; - acpi_integer present_rate; - acpi_integer remaining_capacity; - acpi_integer present_voltage; -}; - -struct acpi_battery_info { - acpi_integer power_unit; - acpi_integer design_capacity; - acpi_integer last_full_capacity; - acpi_integer battery_technology; - acpi_integer design_voltage; - acpi_integer design_capacity_warning; - acpi_integer design_capacity_low; - acpi_integer battery_capacity_granularity_1; - acpi_integer battery_capacity_granularity_2; - acpi_string model_number; - acpi_string serial_number; - acpi_string battery_type; - acpi_string oem_info; -}; - -struct acpi_battery_flags { - u8 present:1; /* Bay occupied? */ - u8 power_unit:1; /* 0=watts, 1=apms */ - u8 alarm:1; /* _BTP present? */ - u8 reserved:5; -}; - -struct acpi_battery_trips { - unsigned long warning; - unsigned long low; -}; - -struct acpi_battery { - acpi_handle handle; - struct acpi_battery_flags flags; - struct acpi_battery_trips trips; - unsigned long alarm; - struct acpi_battery_info *info; -}; - - -/* -------------------------------------------------------------------------- - Battery Management - -------------------------------------------------------------------------- */ - -static int -acpi_battery_get_info ( - struct acpi_battery *battery, - struct acpi_battery_info **bif) -{ - int result = 0; - acpi_status status = 0; - acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BIF), - ACPI_BATTERY_FORMAT_BIF}; - acpi_buffer data = {0, NULL}; - acpi_object *package = NULL; - - ACPI_FUNCTION_TRACE("acpi_battery_get_info"); - - if (!battery || !bif) - return_VALUE(-EINVAL); - - /* Evalute _BIF */ - - status = acpi_evaluate_object(battery->handle, "_BIF", NULL, &buffer); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BIF\n")); - return_VALUE(-ENODEV); - } - - package = (acpi_object *) buffer.pointer; - - /* Extract Package Data */ - - status = acpi_extract_package(package, &format, &data); - if (status != AE_BUFFER_OVERFLOW) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n")); - result = -ENODEV; - goto end; - } - - data.pointer = kmalloc(data.length, GFP_KERNEL); - if (!data.pointer) { - result = -ENOMEM; - goto end; - } - memset(data.pointer, 0, data.length); - - status = acpi_extract_package(package, &format, &data); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n")); - kfree(data.pointer); - result = -ENODEV; - goto end; - } - -end: - kfree(buffer.pointer); - - if (0 == result) - (*bif) = (struct acpi_battery_info *) data.pointer; - - return_VALUE(result); -} - -static int -acpi_battery_get_status ( - struct acpi_battery *battery, - struct acpi_battery_status **bst) -{ - int result = 0; - acpi_status status = 0; - acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BST), - ACPI_BATTERY_FORMAT_BST}; - acpi_buffer data = {0, NULL}; - acpi_object *package = NULL; - - ACPI_FUNCTION_TRACE("acpi_battery_get_status"); - - if (!battery || !bst) - return_VALUE(-EINVAL); - - /* Evalute _BST */ - - status = acpi_evaluate_object(battery->handle, "_BST", NULL, &buffer); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BST\n")); - return_VALUE(-ENODEV); - } - - package = (acpi_object *) buffer.pointer; - - /* Extract Package Data */ - - status = acpi_extract_package(package, &format, &data); - if (status != AE_BUFFER_OVERFLOW) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n")); - result = -ENODEV; - goto end; - } - - data.pointer = kmalloc(data.length, GFP_KERNEL); - if (!data.pointer) { - result = -ENOMEM; - goto end; - } - memset(data.pointer, 0, data.length); - - status = acpi_extract_package(package, &format, &data); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n")); - kfree(data.pointer); - result = -ENODEV; - goto end; - } - -end: - kfree(buffer.pointer); - - if (0 == result) - (*bst) = (struct acpi_battery_status *) data.pointer; - - return_VALUE(result); -} - - -static int -acpi_battery_set_alarm ( - struct acpi_battery *battery, - unsigned long alarm) -{ - acpi_status status = 0; - acpi_object arg0 = {ACPI_TYPE_INTEGER}; - acpi_object_list arg_list = {1, &arg0}; - - ACPI_FUNCTION_TRACE("acpi_battery_set_alarm"); - - if (!battery) - return_VALUE(-EINVAL); - - if (!battery->flags.alarm) - return_VALUE(-ENODEV); - - arg0.integer.value = alarm; - - status = acpi_evaluate(battery->handle, "_BTP", &arg_list, NULL); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm)); - - battery->alarm = alarm; - - return_VALUE(0); -} - - -static int -acpi_battery_check ( - struct acpi_battery *battery) -{ - int result = 0; - acpi_status status = AE_OK; - acpi_handle handle = NULL; - struct acpi_device *device = NULL; - struct acpi_battery_info *bif = NULL; - - ACPI_FUNCTION_TRACE("acpi_battery_check"); - - if (!battery) - return_VALUE(-EINVAL); - - result = acpi_bus_get_device(battery->handle, &device); - if (0 != result) - return_VALUE(result); - - result = acpi_bus_get_status(device); - if (0 != result) - return_VALUE(result); - - /* Insertion? */ - - if (!battery->flags.present && device->status.battery_present) { - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n")); - - /* Evalute _BIF to get certain static information */ - - result = acpi_battery_get_info(battery, &bif); - if (0 != result) - return_VALUE(result); - - battery->flags.power_unit = bif->power_unit; - battery->trips.warning = bif->design_capacity_warning; - battery->trips.low = bif->design_capacity_low; - kfree(bif); - - /* See if alarms are supported, and if so, set default */ - - status = acpi_get_handle(battery->handle, "_BTP", &handle); - if (ACPI_SUCCESS(status)) { - battery->flags.alarm = 1; - acpi_battery_set_alarm(battery, battery->trips.warning); - } - } - - /* Removal? */ - - else if (battery->flags.present && !device->status.battery_present) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n")); - } - - battery->flags.present = device->status.battery_present; - - return_VALUE(result); -} - - -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -#include -#include - -struct proc_dir_entry *acpi_battery_dir = NULL; - -static int -acpi_battery_read_info ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - int result = 0; - struct acpi_battery *battery = (struct acpi_battery *) data; - struct acpi_battery_info *bif = NULL; - char *units = "?"; - char *p = page; - int len = 0; - - ACPI_FUNCTION_TRACE("acpi_battery_read_info"); - - if (!battery) - goto end; - - if (battery->flags.present) - p += sprintf(p, "present: yes\n"); - else { - p += sprintf(p, "present: no\n"); - goto end; - } - - /* Battery Info (_BIF) */ - - result = acpi_battery_get_info(battery, &bif); - if ((0 != result) || !bif) { - p += sprintf(p, "ERROR: Unable to read battery information\n"); - goto end; - } - - units = bif->power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; - - if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) - p += sprintf(p, "design capacity: unknown\n"); - else - p += sprintf(p, "design capacity: %d %sh\n", - (u32) bif->design_capacity, units); - - if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) - p += sprintf(p, "last full capacity: unknown\n"); - else - p += sprintf(p, "last full capacity: %d %sh\n", - (u32) bif->last_full_capacity, units); - - switch ((u32) bif->battery_technology) { - case 0: - p += sprintf(p, "battery technology: non-rechargeable\n"); - break; - case 1: - p += sprintf(p, "battery technology: rechargeable\n"); - break; - default: - p += sprintf(p, "battery technology: unknown\n"); - break; - } - - if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) - p += sprintf(p, "design voltage: unknown\n"); - else - p += sprintf(p, "design voltage: %d mV\n", - (u32) bif->design_voltage); - - p += sprintf(p, "design capacity warning: %d %sh\n", - (u32) bif->design_capacity_warning, units); - p += sprintf(p, "design capacity low: %d %sh\n", - (u32) bif->design_capacity_low, units); - p += sprintf(p, "capacity granularity 1: %d %sh\n", - (u32) bif->battery_capacity_granularity_1, units); - p += sprintf(p, "capacity granularity 2: %d %sh\n", - (u32) bif->battery_capacity_granularity_2, units); - p += sprintf(p, "model number: %s\n", - bif->model_number); - p += sprintf(p, "serial number: %s\n", - bif->serial_number); - p += sprintf(p, "battery type: %s\n", - bif->battery_type); - p += sprintf(p, "OEM info: %s\n", - bif->oem_info); - -end: - kfree(bif); - - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_battery_read_state ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - int result = 0; - struct acpi_battery *battery = (struct acpi_battery *) data; - struct acpi_battery_status *bst = NULL; - char *units = "?"; - char *p = page; - int len = 0; - - ACPI_FUNCTION_TRACE("acpi_battery_read_state"); - - if (!battery) - goto end; - - if (battery->flags.present) - p += sprintf(p, "present: yes\n"); - else { - p += sprintf(p, "present: no\n"); - goto end; - } - - /* Battery Units */ - - units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; - - /* Battery Status (_BST) */ - - result = acpi_battery_get_status(battery, &bst); - if ((0 != result) || !bst) { - p += sprintf(p, "ERROR: Unable to read battery status\n"); - goto end; - } - - if (!(bst->state & 0x04)) - p += sprintf(p, "capacity state: ok\n"); - else - p += sprintf(p, "capacity state: critical\n"); - - if ((bst->state & 0x01) && (bst->state & 0x02)) - p += sprintf(p, "charging state: charging/discharging\n"); - else if (bst->state & 0x01) - p += sprintf(p, "charging state: discharging\n"); - else if (bst->state & 0x02) - p += sprintf(p, "charging state: charging\n"); - else - p += sprintf(p, "charging state: unknown\n"); - - if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN) - p += sprintf(p, "present rate: unknown\n"); - else - p += sprintf(p, "present rate: %d %s\n", - (u32) bst->present_rate, units); - - if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN) - p += sprintf(p, "remaining capacity: unknown\n"); - else - p += sprintf(p, "remaining capacity: %d %sh\n", - (u32) bst->remaining_capacity, units); - - if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN) - p += sprintf(p, "present voltage: unknown\n"); - else - p += sprintf(p, "present voltage: %d mV\n", - (u32) bst->present_voltage); - -end: - kfree(bst); - - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_battery_read_alarm ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_battery *battery = (struct acpi_battery *) data; - char *units = "?"; - char *p = page; - int len = 0; - - ACPI_FUNCTION_TRACE("acpi_battery_read_alarm"); - - if (!battery) - goto end; - - if (!battery->flags.present) { - p += sprintf(p, "present: no\n"); - goto end; - } - - /* Battery Units */ - - units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; - - /* Battery Alarm */ - - p += sprintf(p, "alarm: "); - if (!battery->alarm) - p += sprintf(p, "unsupported\n"); - else - p += sprintf(p, "%d %sh\n", (u32) battery->alarm, units); - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_battery_write_alarm ( - struct file *file, - const char *buffer, - unsigned long count, - void *data) -{ - int result = 0; - struct acpi_battery *battery = (struct acpi_battery *) data; - char alarm_string[12] = {'\0'}; - - ACPI_FUNCTION_TRACE("acpi_battery_write_alarm"); - - if (!battery || (count > sizeof(alarm_string) - 1)) - return_VALUE(-EINVAL); - - if (!battery->flags.present) - return_VALUE(-ENODEV); - - if (copy_from_user(alarm_string, buffer, count)) - return_VALUE(-EFAULT); - - alarm_string[count] = '\0'; - - result = acpi_battery_set_alarm(battery, - simple_strtoul(alarm_string, NULL, 0)); - if (0 != result) - return_VALUE(result); - - return_VALUE(count); -} - - -static int -acpi_battery_add_fs ( - struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - - ACPI_FUNCTION_TRACE("acpi_battery_add_fs"); - - if (!acpi_battery_dir) { - acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir); - if (!acpi_battery_dir) - return_VALUE(-ENODEV); - } - - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_battery_dir); - if (!acpi_device_dir(device)) - return_VALUE(-ENODEV); - } - - /* 'info' [R] */ - entry = create_proc_entry(ACPI_BATTERY_FILE_INFO, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_BATTERY_FILE_INFO)); - else { - entry->read_proc = acpi_battery_read_info; - entry->data = acpi_driver_data(device); - } - - /* 'status' [R] */ - entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_BATTERY_FILE_STATUS)); - else { - entry->read_proc = acpi_battery_read_state; - entry->data = acpi_driver_data(device); - } - - /* 'alarm' [R/W] */ - entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_BATTERY_FILE_ALARM)); - else { - entry->read_proc = acpi_battery_read_alarm; - entry->write_proc = acpi_battery_write_alarm; - entry->data = acpi_driver_data(device); - } - - return_VALUE(0); -} - - -static int -acpi_battery_remove_fs ( - struct acpi_device *device) -{ - ACPI_FUNCTION_TRACE("acpi_battery_remove_fs"); - - if (!acpi_battery_dir) - return_VALUE(-ENODEV); - - if (acpi_device_dir(device)) - remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ - -static void -acpi_battery_notify ( - acpi_handle handle, - u32 event, - void *data) -{ - struct acpi_battery *battery = (struct acpi_battery *) data; - struct acpi_device *device = NULL; - - ACPI_FUNCTION_TRACE("acpi_battery_notify"); - - if (!battery) - return_VOID; - - if (0 != acpi_bus_get_device(handle, &device)) - return_VOID; - - switch (event) { - case ACPI_BATTERY_NOTIFY_STATUS: - case ACPI_BATTERY_NOTIFY_INFO: - acpi_battery_check(battery); - acpi_bus_generate_event(device, event, battery->flags.present); - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Unsupported event [0x%x]\n", event)); - break; - } - - return_VOID; -} - - -static int -acpi_battery_add ( - struct acpi_device *device) -{ - int result = 0; - acpi_status status = 0; - struct acpi_battery *battery = NULL; - - ACPI_FUNCTION_TRACE("acpi_battery_add"); - - if (!device) - return_VALUE(-EINVAL); - - battery = kmalloc(sizeof(struct acpi_battery), GFP_KERNEL); - if (!battery) - return_VALUE(-ENOMEM); - memset(battery, 0, sizeof(struct acpi_battery)); - - battery->handle = device->handle; - sprintf(acpi_device_name(device), "%s", ACPI_BATTERY_DEVICE_NAME); - sprintf(acpi_device_class(device), "%s", ACPI_BATTERY_CLASS); - acpi_driver_data(device) = battery; - - result = acpi_battery_check(battery); - if (0 != result) - goto end; - - result = acpi_battery_add_fs(device); - if (0 != result) - goto end; - - status = acpi_install_notify_handler(battery->handle, - ACPI_DEVICE_NOTIFY, acpi_battery_notify, battery); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error installing notify handler\n")); - result = -ENODEV; - goto end; - } - - printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", - ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), - device->status.battery_present?"present":"absent"); - -end: - if (0 != result) { - acpi_battery_remove_fs(device); - kfree(battery); - } - - return_VALUE(result); -} - - -static int -acpi_battery_remove ( - struct acpi_device *device, - int type) -{ - acpi_status status = 0; - struct acpi_battery *battery = NULL; - - ACPI_FUNCTION_TRACE("acpi_battery_remove"); - - if (!device || !acpi_driver_data(device)) - return_VALUE(-EINVAL); - - battery = (struct acpi_battery *) acpi_driver_data(device); - - status = acpi_remove_notify_handler(battery->handle, - ACPI_DEVICE_NOTIFY, acpi_battery_notify); - if (ACPI_FAILURE(status)) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error removing notify handler\n")); - - acpi_battery_remove_fs(device); - - kfree(battery); - - return_VALUE(0); -} - - -static int __init -acpi_battery_init (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_battery_init"); - - result = acpi_bus_register_driver(&acpi_battery_driver); - if (0 > result) { - remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); - return_VALUE(-ENODEV); - } - - return_VALUE(0); -} - - -static void __exit -acpi_battery_exit (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_battery_exit"); - - result = acpi_bus_unregister_driver(&acpi_battery_driver); - if (0 == result) - remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); - - return_VOID; -} - - -module_init(acpi_battery_init); -module_exit(acpi_battery_exit); diff -Nru a/drivers/acpi/acpi_bus.c b/drivers/acpi/acpi_bus.c --- a/drivers/acpi/acpi_bus.c Sun Jun 2 18:44:58 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,2201 +0,0 @@ -/* - * acpi_bus.c - ACPI Bus Driver ($Revision: 66 $) - * - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "acpi_bus.h" -#include "acpi_drivers.h" -#include "include/acinterp.h" /* for acpi_ex_eisa_id_to_string() */ - - -#define _COMPONENT ACPI_BUS_COMPONENT -ACPI_MODULE_NAME ("acpi_bus") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_BUS_DRIVER_NAME); -MODULE_LICENSE("GPL"); - -#define PREFIX "ACPI: " - -FADT_DESCRIPTOR acpi_fadt; -static u8 acpi_disabled = 0; -struct acpi_device *acpi_root = NULL; -struct proc_dir_entry *acpi_root_dir = NULL; - -#define STRUCT_TO_INT(s) (*((int*)&s)) - -/* - * POLICY: If *anything* doesn't work, put it on the blacklist. - * If they are critical errors, mark it critical, and abort driver load. - */ -static struct acpi_blacklist_item acpi_blacklist[] __initdata = -{ - /* Portege 7020, BIOS 8.10 */ - {"TOSHIB", "7020CT ", 0x19991112, ACPI_TABLE_DSDT, all_versions, "Implicit Return", 0}, - /* Portege 4030 */ - {"TOSHIB", "4030 ", 0x19991112, ACPI_TABLE_DSDT, all_versions, "Implicit Return", 0}, - /* Portege 310/320, BIOS 7.1 */ - {"TOSHIB", "310 ", 0x19990511, ACPI_TABLE_DSDT, all_versions, "Implicit Return", 0}, - /* Seattle 2, old bios rev. */ - {"INTEL ", "440BX ", 0x00001000, ACPI_TABLE_DSDT, less_than_or_equal, "Field beyond end of region", 0}, - /* ASUS K7M */ - {"ASUS ", "K7M ", 0x00001000, ACPI_TABLE_DSDT, less_than_or_equal, "Field beyond end of region", 0}, - /* Intel 810 Motherboard? */ - {"MNTRAL", "MO81010A", 0x00000012, ACPI_TABLE_DSDT, less_than_or_equal, "Field beyond end of region", 0}, - /* Compaq Presario 1700 */ - {"PTLTD ", " DSDT ", 0x06040000, ACPI_TABLE_DSDT, less_than_or_equal, "Multiple problems", 1}, - /* Sony FX120, FX140, FX150? */ - {"SONY ", "U0 ", 0x20010313, ACPI_TABLE_DSDT, less_than_or_equal, "ACPI driver problem", 1}, - /* Compaq Presario 800, Insyde BIOS */ - {"INT440", "SYSFexxx", 0x00001001, ACPI_TABLE_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1}, - /* IBM 600E - _ADR should return 7, but it returns 1 */ - {"IBM ", "TP600E ", 0x00000105, ACPI_TABLE_DSDT, less_than_or_equal, "Incorrect _ADR", 1}, - {""} -}; - - -/* -------------------------------------------------------------------------- - Linux Driver Model (LDM) Support - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_LDM - -static int acpi_device_probe(struct device *dev); -static int acpi_device_remove(struct device *dev, u32 flags); -static int acpi_device_suspend(struct device *dev, u32 state, u32 stage); -static int acpi_device_resume(struct device *dev, u32 stage); - -static struct device_driver acpi_bus_driver = { - probe: acpi_device_probe, - remove: acpi_device_remove, - suspend: acpi_device_suspend, - resume: acpi_device_resume, -}; - - -static int -acpi_device_probe ( - struct device *dev) -{ - ACPI_FUNCTION_TRACE("acpi_device_probe"); - - if (!dev) - return_VALUE(-EINVAL); - - /* TBD */ - - return_VALUE(0); -} - - -static int -acpi_device_remove ( - struct device *dev, - u32 flags) -{ - ACPI_FUNCTION_TRACE("acpi_device_remove"); - - if (!dev) - return_VALUE(-EINVAL); - - /* TBD */ - - return_VALUE(0); -} - - -static int -acpi_device_suspend ( - struct device *dev, - u32 state, - u32 stage) -{ - ACPI_FUNCTION_TRACE("acpi_device_suspend"); - - if (!dev) - return_VALUE(-EINVAL); - - /* TBD */ - - return_VALUE(0); -} - - -static int -acpi_device_resume ( - struct device *dev, - u32 stage) -{ - ACPI_FUNCTION_TRACE("acpi_device_resume"); - - if (!dev) - return_VALUE(-EINVAL); - - /* TBD */ - - return_VALUE(0); -} - -#if 0 /* not used ATM */ -static int -acpi_platform_add ( - struct device *dev) -{ - ACPI_FUNCTION_TRACE("acpi_platform_add"); - - if (!dev) - return -EINVAL; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s (%s) added\n", - dev->name, dev->bus_id)); - - /* TBD */ - - return_VALUE(0); -} - - -static int -acpi_platform_remove ( - struct device *dev) -{ - ACPI_FUNCTION_TRACE("acpi_platform_add"); - - if (!dev) - return -EINVAL; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s (%s) removed\n", - dev->name, dev->bus_id)); - - /* TBD */ - - return_VALUE(0); -} -#endif /* unused */ - - -#endif /*CONFIG_LDM*/ - - -static int -acpi_device_register ( - struct acpi_device *device, - struct acpi_device *parent) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_device_register"); - - if (!device) - return_VALUE(-EINVAL); - -#ifdef CONFIG_LDM - sprintf(device->dev.name, "ACPI device %s:%s", - device->pnp.hardware_id, device->pnp.unique_id); - strncpy(device->dev.bus_id, device->pnp.bus_id, sizeof(acpi_bus_id)); - if (parent) - device->dev.parent = &parent->dev; - device->dev.driver = &acpi_bus_driver; - - result = device_register(&device->dev); -#endif /*CONFIG_LDM*/ - - return_VALUE(result); -} - - -static int -acpi_device_unregister ( - struct acpi_device *device) -{ - ACPI_FUNCTION_TRACE("acpi_device_unregister"); - - if (!device) - return_VALUE(-EINVAL); - -#ifdef CONFIG_LDM - put_device(&device->dev); -#endif /*CONFIG_LDM*/ - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Device Management - -------------------------------------------------------------------------- */ - -static void -acpi_bus_data_handler ( - acpi_handle handle, - u32 function, - void *context) -{ - ACPI_FUNCTION_TRACE("acpi_bus_data_handler"); - - /* TBD */ - - return_VOID; -} - - -int -acpi_bus_get_device ( - acpi_handle handle, - struct acpi_device **device) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE("acpi_bus_get_device"); - - if (!device) - return_VALUE(-EINVAL); - - /* TBD: Support fixed-feature devices */ - - status = acpi_get_data(handle, acpi_bus_data_handler, (void**) device); - if (ACPI_FAILURE(status) || !*device) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error getting context for object [%p]\n", - handle)); - return_VALUE(-ENODEV); - } - - return_VALUE(0); -} - -int -acpi_bus_get_status ( - struct acpi_device *device) -{ - acpi_status status = AE_OK; - unsigned long sta = 0; - - ACPI_FUNCTION_TRACE("acpi_bus_get_status"); - - if (!device) - return_VALUE(-EINVAL); - - /* - * Evaluate _STA if present. - */ - if (device->flags.dynamic_status) { - status = acpi_evaluate_integer(device->handle, "_STA", NULL, &sta); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - STRUCT_TO_INT(device->status) = (int) sta; - } - - /* - * Otherwise we assume the status of our parent (unless we don't - * have one, in which case status is implied). - */ - else if (device->parent) - device->status = device->parent->status; - else - STRUCT_TO_INT(device->status) = 0x0F; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", - device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status))); - - return_VALUE(0); -} - - -/* -static int -acpi_bus_create_device_fs (struct device *device) -{ - ACPI_FUNCTION_TRACE("acpi_bus_create_device_fs"); - - if (!device) - return_VALUE(-EINVAL); - - if (device->dir.entry) - return_VALUE(-EEXIST); - - if (!device->parent) - device->dir.entry = proc_mkdir(device->pnp.bus_id, NULL); - else - device->dir.entry = proc_mkdir(device->pnp.bus_id, - device->parent->fs.entry); - - if (!device->dir.entry) { - printk(KERN_ERR PREFIX "Unable to create fs entry '%s'\n", - device->pnp.bus_id); - return_VALUE(-ENODEV); - } - - return_VALUE(0); -} - - -static int -acpi_bus_remove_device_fs (struct device *device) -{ - ACPI_FUNCTION_TRACE("acpi_bus_create_device_fs"); - - if (!device) - return_VALUE(-EINVAL); - - if (!device->dir.entry) - return_VALUE(-ENODEV); - - if (!device->parent) - remove_proc_entry(device->pnp_bus_id, NULL); - else - remove_proc_entry(device->pnp.bus_id, device->parent->fs.entry); - - device->dir.entry = NULL; - - return_VALUE(0); -} -*/ - - -/* -------------------------------------------------------------------------- - Power Management - -------------------------------------------------------------------------- */ - -int -acpi_bus_get_power ( - acpi_handle handle, - int *state) -{ - int result = 0; - acpi_status status = 0; - struct acpi_device *device = NULL; - unsigned long psc = 0; - - ACPI_FUNCTION_TRACE("acpi_bus_get_power"); - - result = acpi_bus_get_device(handle, &device); - if (0 != result) - return_VALUE(result); - - *state = ACPI_STATE_UNKNOWN; - - if (!device->flags.power_manageable) { - /* TBD: Non-recursive algorithm for walking up hierarchy */ - if (device->parent) - *state = device->parent->power.state; - else - *state = ACPI_STATE_D0; - } - else { - /* - * Get the device's power state either directly (via _PSC) or - * indirectly (via power resources). - */ - if (device->power.flags.explicit_get) { - status = acpi_evaluate_integer(device->handle, "_PSC", - NULL, &psc); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - device->power.state = (int) psc; - } - else if (device->power.flags.power_resources) { - result = acpi_power_get_inferred_state(device); - if (0 != result) - return_VALUE(result); - } - - *state = device->power.state; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", - device->pnp.bus_id, device->power.state)); - - return_VALUE(0); -} - - -int -acpi_bus_set_power ( - acpi_handle handle, - int state) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_device *device = NULL; - char object_name[5] = {'_','P','S','0'+state,'\0'}; - - ACPI_FUNCTION_TRACE("acpi_bus_set_power"); - - result = acpi_bus_get_device(handle, &device); - if (0 != result) - return_VALUE(result); - - if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) - return_VALUE(-EINVAL); - - /* Make sure this is a valid target state */ - - if (!device->flags.power_manageable) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device is not power manageable\n")); - return_VALUE(-ENODEV); - } - if (state == device->power.state) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state)); - return_VALUE(0); - } - if (!device->power.states[state].flags.valid) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n", state)); - return_VALUE(-ENODEV); - } - if (device->parent && (state < device->parent->power.state)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Cannot set device to a higher-powered state than parent\n")); - return_VALUE(-ENODEV); - } - - /* - * Transition Power - * ---------------- - * On transitions to a high-powered state we first apply power (via - * power resources) then evalute _PSx. Conversly for transitions to - * a lower-powered state. - */ - if (state < device->power.state) { - if (device->power.flags.power_resources) { - result = acpi_power_transition(device, state); - if (0 != result) - goto end; - } - if (device->power.states[state].flags.explicit_set) { - status = acpi_evaluate_object(device->handle, - object_name, NULL, NULL); - if (ACPI_FAILURE(status)) { - result = -ENODEV; - goto end; - } - } - } - else { - if (device->power.states[state].flags.explicit_set) { - status = acpi_evaluate_object(device->handle, - object_name, NULL, NULL); - if (ACPI_FAILURE(status)) { - result = -ENODEV; - goto end; - } - } - if (device->power.flags.power_resources) { - result = acpi_power_transition(device, state); - if (0 != result) - goto end; - } - } - -end: - if (0 != result) - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error transitioning device [%s] to D%d\n", - device->pnp.bus_id, state)); - else - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] transitioned to D%d\n", - device->pnp.bus_id, state)); - - return_VALUE(result); -} - - -static int -acpi_bus_get_power_flags ( - struct acpi_device *device) -{ - acpi_status status = 0; - acpi_handle handle = 0; - u32 i = 0; - - ACPI_FUNCTION_TRACE("acpi_bus_get_power_flags"); - - if (!device) - return -ENODEV; - - /* - * Power Management Flags - */ - status = acpi_get_handle(device->handle, "_PSC", &handle); - if (ACPI_SUCCESS(status)) - device->power.flags.explicit_get = 1; - status = acpi_get_handle(device->handle, "_IRC", &handle); - if (ACPI_SUCCESS(status)) - device->power.flags.inrush_current = 1; - status = acpi_get_handle(device->handle, "_PRW", &handle); - if (ACPI_SUCCESS(status)) - device->power.flags.wake_capable = 1; - - /* - * Enumerate supported power management states - */ - for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) { - struct acpi_device_power_state *ps = &device->power.states[i]; - char object_name[5] = {'_','P','R','0'+i,'\0'}; - - /* Evaluate "_PRx" to se if power resources are referenced */ - acpi_evaluate_reference(device->handle, object_name, NULL, - &ps->resources); - if (ps->resources.count) { - device->power.flags.power_resources = 1; - ps->flags.valid = 1; - } - - /* Evaluate "_PSx" to see if we can do explicit sets */ - object_name[2] = 'S'; - status = acpi_get_handle(device->handle, object_name, &handle); - if (ACPI_SUCCESS(status)) { - ps->flags.explicit_set = 1; - ps->flags.valid = 1; - } - - /* State is valid if we have some power control */ - if (ps->resources.count || ps->flags.explicit_set) - ps->flags.valid = 1; - - ps->power = -1; /* Unknown - driver assigned */ - ps->latency = -1; /* Unknown - driver assigned */ - } - - /* Set defaults for D0 and D3 states (always valid) */ - device->power.states[ACPI_STATE_D0].flags.valid = 1; - device->power.states[ACPI_STATE_D0].power = 100; - device->power.states[ACPI_STATE_D3].flags.valid = 1; - device->power.states[ACPI_STATE_D3].power = 0; - - /* - * System Power States - * ------------------- - */ - /* TBD: S1-S4 power state support and resource requirements. */ - /* - for (i=ACPI_STATE_S1; ihandle, name, NULL, - &state); - if (ACPI_FAILURE(status)) - continue; - } - */ - - /* TBD: System wake support and resource requirements. */ - - device->power.state = ACPI_STATE_UNKNOWN; - - return 0; -} - - -/* -------------------------------------------------------------------------- - Performance Management - -------------------------------------------------------------------------- */ - -static int -acpi_bus_get_perf_flags ( - struct acpi_device *device) -{ - ACPI_FUNCTION_TRACE("acpi_bus_get_perf_flags"); - - if (!device) - return -ENODEV; - - device->performance.state = ACPI_STATE_UNKNOWN; - - return 0; -} - - -/* -------------------------------------------------------------------------- - Event Management - -------------------------------------------------------------------------- */ - -static spinlock_t acpi_bus_event_lock = SPIN_LOCK_UNLOCKED; - -LIST_HEAD(acpi_bus_event_list); -DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue); - -extern int event_is_open; - -int -acpi_bus_generate_event ( - struct acpi_device *device, - u8 type, - int data) -{ - struct acpi_bus_event *event = NULL; - u32 flags = 0; - - ACPI_FUNCTION_TRACE("acpi_bus_generate_event"); - - if (!device) - return_VALUE(-EINVAL); - - /* drop event on the floor if no one's listening */ - if (!event_is_open) - return_VALUE(0); - - event = kmalloc(sizeof(struct acpi_bus_event), GFP_KERNEL); - if (!event) - return_VALUE(-ENOMEM); - - sprintf(event->device_class, "%s", device->pnp.device_class); - sprintf(event->bus_id, "%s", device->pnp.bus_id); - event->type = type; - event->data = data; - - spin_lock_irqsave(&acpi_bus_event_lock, flags); - list_add_tail(&event->node, &acpi_bus_event_list); - spin_unlock_irqrestore(&acpi_bus_event_lock, flags); - - wake_up_interruptible(&acpi_bus_event_queue); - - return_VALUE(0); -} - -int -acpi_bus_receive_event ( - struct acpi_bus_event *event) -{ - u32 flags = 0; - struct acpi_bus_event *entry = NULL; - - DECLARE_WAITQUEUE(wait, current); - - ACPI_FUNCTION_TRACE("acpi_bus_receive_event"); - - if (!event) - return -EINVAL; - - if (list_empty(&acpi_bus_event_list)) { - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&acpi_bus_event_queue, &wait); - - if (list_empty(&acpi_bus_event_list)) - schedule(); - - remove_wait_queue(&acpi_bus_event_queue, &wait); - set_current_state(TASK_RUNNING); - - if (signal_pending(current)) - return_VALUE(-ERESTARTSYS); - } - - spin_lock_irqsave(&acpi_bus_event_lock, flags); - entry = list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node); - if (entry) - list_del(&entry->node); - spin_unlock_irqrestore(&acpi_bus_event_lock, flags); - - if (!entry) - return_VALUE(-ENODEV); - - memcpy(event, entry, sizeof(struct acpi_bus_event)); - - kfree(entry); - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Namespace Management - -------------------------------------------------------------------------- */ - -#define WALK_UP 0 -#define WALK_DOWN 1 - -typedef int (*acpi_bus_walk_callback)(struct acpi_device*, int, void*); - -#define HAS_CHILDREN(d) ((d)->children.next != &((d)->children)) -#define HAS_SIBLINGS(d) (((d)->parent) && ((d)->node.next != &(d)->parent->children)) -#define NODE_TO_DEVICE(n) (list_entry(n, struct acpi_device, node)) - - -/** - * acpi_bus_walk - * ------------- - * Used to walk the ACPI Bus's device namespace. Can walk down (depth-first) - * or up. Able to parse starting at any node in the namespace. Note that a - * callback return value of -ELOOP will terminate the walk. - * - * @start: starting point - * callback: function to call for every device encountered while parsing - * direction: direction to parse (up or down) - * @data: context for this search operation - */ -static int -acpi_bus_walk ( - struct acpi_device *start, - acpi_bus_walk_callback callback, - int direction, - void *data) -{ - int result = 0; - int level = 0; - struct acpi_device *device = NULL; - - if (!start || !callback) - return -EINVAL; - - device = start; - - /* - * Parse Namespace - * --------------- - * Parse a given subtree (specified by start) in the given direction. - * Walking 'up' simply means that we execute the callback on leaf - * devices prior to their parents (useful for things like removing - * or powering down a subtree). - */ - - while (device) { - - if (direction == WALK_DOWN) - if (-ELOOP == callback(device, level, data)) - break; - - /* Depth First */ - - if (HAS_CHILDREN(device)) { - device = NODE_TO_DEVICE(device->children.next); - ++level; - continue; - } - - if (direction == WALK_UP) - if (-ELOOP == callback(device, level, data)) - break; - - /* Now Breadth */ - - if (HAS_SIBLINGS(device)) { - device = NODE_TO_DEVICE(device->node.next); - continue; - } - - /* Scope Exhausted - Find Next */ - - while ((device = device->parent)) { - --level; - if (HAS_SIBLINGS(device)) { - device = NODE_TO_DEVICE(device->node.next); - break; - } - } - } - - if ((direction == WALK_UP) && (result == 0)) - callback(start, level, data); - - return result; -} - - -/* -------------------------------------------------------------------------- - Notification Handling - -------------------------------------------------------------------------- */ - -static int -acpi_bus_check_device ( - struct acpi_device *device, - int *status_changed) -{ - acpi_status status = 0; - struct acpi_device_status old_status; - - ACPI_FUNCTION_TRACE("acpi_bus_check_device"); - - if (!device) - return_VALUE(-EINVAL); - - if (status_changed) - *status_changed = 0; - - old_status = device->status; - - /* - * Make sure this device's parent is present before we go about - * messing with the device. - */ - if (device->parent && !device->parent->status.present) { - device->status = device->parent->status; - if (STRUCT_TO_INT(old_status) != STRUCT_TO_INT(device->status)) { - if (status_changed) - *status_changed = 1; - } - return_VALUE(0); - } - - status = acpi_bus_get_status(device); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) - return_VALUE(0); - - if (status_changed) - *status_changed = 1; - - /* - * Device Insertion/Removal - */ - if ((device->status.present) && !(old_status.present)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n")); - /* TBD: Handle device insertion */ - } - else if (!(device->status.present) && (old_status.present)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); - /* TBD: Handle device removal */ - } - - return_VALUE(0); -} - - -static int -acpi_bus_check_scope ( - struct acpi_device *device) -{ - int result = 0; - int status_changed = 0; - - ACPI_FUNCTION_TRACE("acpi_bus_check_scope"); - - if (!device) - return_VALUE(-EINVAL); - - /* Status Change? */ - result = acpi_bus_check_device(device, &status_changed); - if (0 != result) - return_VALUE(result); - - if (!status_changed) - return_VALUE(0); - - /* - * TBD: Enumerate child devices within this device's scope and - * run acpi_bus_check_device()'s on them. - */ - - return_VALUE(0); -} - - -/** - * acpi_bus_notify - * --------------- - * Callback for all 'system-level' device notifications (values 0x00-0x7F). - */ -static void -acpi_bus_notify ( - acpi_handle handle, - u32 type, - void *data) -{ - int result = 0; - struct acpi_device *device = NULL; - - ACPI_FUNCTION_TRACE("acpi_bus_notify"); - - if (0 != acpi_bus_get_device(handle, &device)) - return_VOID; - - switch (type) { - - case ACPI_NOTIFY_BUS_CHECK: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS CHECK notification for device [%s]\n", - device->pnp.bus_id)); - result = acpi_bus_check_scope(device); - /* - * TBD: We'll need to outsource certain events to non-ACPI - * drivers via the device manager (device.c). - */ - break; - - case ACPI_NOTIFY_DEVICE_CHECK: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK notification for device [%s]\n", - device->pnp.bus_id)); - result = acpi_bus_check_device(device, NULL); - /* - * TBD: We'll need to outsource certain events to non-ACPI - * drivers via the device manager (device.c). - */ - break; - - case ACPI_NOTIFY_DEVICE_WAKE: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE WAKE notification for device [%s]\n", - device->pnp.bus_id)); - /* TBD */ - break; - - case ACPI_NOTIFY_EJECT_REQUEST: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received EJECT REQUEST notification for device [%s]\n", - device->pnp.bus_id)); - /* TBD */ - break; - - case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK LIGHT notification for device [%s]\n", - device->pnp.bus_id)); - /* TBD: Exactly what does 'light' mean? */ - break; - - case ACPI_NOTIFY_FREQUENCY_MISMATCH: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received FREQUENCY MISMATCH notification for device [%s]\n", - device->pnp.bus_id)); - /* TBD */ - break; - - case ACPI_NOTIFY_BUS_MODE_MISMATCH: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS MODE MISMATCH notification for device [%s]\n", - device->pnp.bus_id)); - /* TBD */ - break; - - case ACPI_NOTIFY_POWER_FAULT: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received POWER FAULT notification for device [%s]\n", - device->pnp.bus_id)); - /* TBD */ - break; - - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received unknown/unsupported notification [%08x]\n", - type)); - break; - } - - return_VOID; -} - - -/* -------------------------------------------------------------------------- - Driver Management - -------------------------------------------------------------------------- */ - -static LIST_HEAD(acpi_bus_drivers); -static DECLARE_MUTEX(acpi_bus_drivers_lock); - - -/** - * acpi_bus_match - * -------------- - * Checks the device's hardware (_HID) or compatible (_CID) ids to see if it - * matches the specified driver's criteria. - */ -static int -acpi_bus_match ( - struct acpi_device *device, - struct acpi_driver *driver) -{ - - if (!device || !driver) - return -EINVAL; - - if (device->flags.hardware_id) { - if (0 != strstr(driver->ids, device->pnp.hardware_id)) - return 0; - } - - if (device->flags.compatible_ids) { - acpi_status status = AE_OK; - acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_object *object = NULL; - char cid[256]; - - memset(cid, 0, sizeof(cid)); - - status = acpi_evaluate_object(device->handle, "_CID", NULL, - &buffer); - if (ACPI_FAILURE(status) || !buffer.pointer) - return -ENOENT; - - object = (acpi_object *) buffer.pointer; - - switch (object->type) { - case ACPI_TYPE_INTEGER: - acpi_ex_eisa_id_to_string((u32) object->integer.value, - cid); - break; - case ACPI_TYPE_STRING: - strncpy(cid, object->string.pointer, sizeof(cid) - 1); - break; - case ACPI_TYPE_PACKAGE: - /* TBD: Support CID packages */ - } - - if (!cid[0]) - return -ENOENT; - - if (0 != strstr(cid, device->pnp.hardware_id)) - return 0; - } - - return -ENOENT; -} - - -/** - * acpi_bus_driver_init - * -------------------- - * Used to initialize a device via its device driver. Called whenever a - * driver is bound to a device. Invokes the driver's add() and start() ops. - */ -static int -acpi_bus_driver_init ( - struct acpi_device *device, - struct acpi_driver *driver) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_bus_driver_init"); - - if (!device || !driver) - return_VALUE(-EINVAL); - - if (!driver->ops.add) - return_VALUE(-ENOSYS); - - result = driver->ops.add(device); - if (0 != result) { - device->driver = NULL; - acpi_driver_data(device) = NULL; - return_VALUE(result); - } - - /* - * TBD - Configuration Management: Assign resources to device based - * upon possible configuration and currently allocated resources. - */ - - if (driver->ops.start) { - result = driver->ops.start(device); - if ((0 != result) && (driver->ops.remove)) - driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); - return_VALUE(result); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n")); - -#ifdef CONFIG_LDM - /* - * Update the device information (in the global device hierarchy) now - * that there's a driver bound to it. - */ - strncpy(device->dev.name, device->pnp.device_name, - sizeof(device->dev.name)); -#endif - - if (driver->ops.scan) { - driver->ops.scan(device); - } - - return_VALUE(0); -} - - -/** - * acpi_bus_attach - * ------------- - * Callback for acpi_bus_walk() used to find devices that match a specific - * driver's criteria and then attach the driver. - */ -static int -acpi_bus_attach ( - struct acpi_device *device, - int level, - void *data) -{ - int result = 0; - struct acpi_driver *driver = NULL; - - ACPI_FUNCTION_TRACE("acpi_bus_attach"); - - if (!device || !data) - return_VALUE(-EINVAL); - - driver = (struct acpi_driver *) data; - - if (device->driver) - return_VALUE(-EEXIST); - - if (!device->status.present) - return_VALUE(-ENODEV); - - result = acpi_bus_match(device, driver); - if (0 != result) - return_VALUE(result); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", - driver->name, device->pnp.bus_id)); - - result = acpi_bus_driver_init(device, driver); - if (0 != result) - return_VALUE(result); - - down(&acpi_bus_drivers_lock); - ++driver->references; - up(&acpi_bus_drivers_lock); - - return_VALUE(0); -} - - -/** - * acpi_bus_unattach - * ----------------- - * Callback for acpi_bus_walk() used to find devices that match a specific - * driver's criteria and unattach the driver. - */ -static int -acpi_bus_unattach ( - struct acpi_device *device, - int level, - void *data) -{ - int result = 0; - struct acpi_driver *driver = (struct acpi_driver *) data; - - ACPI_FUNCTION_TRACE("acpi_bus_unattach"); - - if (!device || !driver) - return_VALUE(-EINVAL); - - if (device->driver != driver) - return_VALUE(-ENOENT); - - if (!driver->ops.remove) - return_VALUE(-ENOSYS); - - result = driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); - if (0 != result) - return_VALUE(result); - - device->driver = NULL; - acpi_driver_data(device) = NULL; - - down(&acpi_bus_drivers_lock); - driver->references--; - up(&acpi_bus_drivers_lock); - - return_VALUE(0); -} - - -/** - * acpi_bus_find_driver - * -------------------- - * Parses the list of registered drivers looking for a driver applicable for - * the specified device. - */ -static int -acpi_bus_find_driver ( - struct acpi_device *device) -{ - int result = -ENODEV; - struct list_head *entry = NULL; - struct acpi_driver *driver = NULL; - - ACPI_FUNCTION_TRACE("acpi_bus_find_driver"); - - if (!device || device->driver) - return_VALUE(-EINVAL); - - down(&acpi_bus_drivers_lock); - - list_for_each(entry, &acpi_bus_drivers) { - - driver = list_entry(entry, struct acpi_driver, node); - - if (0 != acpi_bus_match(device, driver)) - continue; - - result = acpi_bus_driver_init(device, driver); - if (0 == result) - ++driver->references; - - break; - } - - up(&acpi_bus_drivers_lock); - - return_VALUE(result); -} - - -/** - * acpi_bus_register_driver - * ------------------------ - * Registers a driver with the ACPI bus. Searches the namespace for all - * devices that match the driver's criteria and binds. - */ -int -acpi_bus_register_driver ( - struct acpi_driver *driver) -{ - ACPI_FUNCTION_TRACE("acpi_bus_register_driver"); - - if (!driver) - return_VALUE(-EINVAL); - - down(&acpi_bus_drivers_lock); - list_add_tail(&driver->node, &acpi_bus_drivers); - up(&acpi_bus_drivers_lock); - - acpi_bus_walk(acpi_root, acpi_bus_attach, - WALK_DOWN, driver); - - return_VALUE(driver->references); -} - - -/** - * acpi_bus_unregister_driver - * -------------------------- - * Unregisters a driver with the ACPI bus. Searches the namespace for all - * devices that match the driver's criteria and unbinds. - */ -int -acpi_bus_unregister_driver ( - struct acpi_driver *driver) -{ - ACPI_FUNCTION_TRACE("acpi_bus_unregister_driver"); - - if (!driver) - return_VALUE(-EINVAL); - - acpi_bus_walk(acpi_root, acpi_bus_unattach, WALK_UP, driver); - - if (driver->references) - return_VALUE(driver->references); - - down(&acpi_bus_drivers_lock); - list_del(&driver->node); - up(&acpi_bus_drivers_lock); - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Device Enumeration - -------------------------------------------------------------------------- */ - -static int -acpi_bus_get_flags ( - struct acpi_device *device) -{ - acpi_status status = AE_OK; - acpi_handle temp = NULL; - - ACPI_FUNCTION_TRACE("acpi_bus_get_flags"); - - /* Presence of _STA indicates 'dynamic_status' */ - status = acpi_get_handle(device->handle, "_STA", &temp); - if (ACPI_SUCCESS(status)) - device->flags.dynamic_status = 1; - - /* Presence of _CID indicates 'compatible_ids' */ - status = acpi_get_handle(device->handle, "_CID", &temp); - if (ACPI_SUCCESS(status)) - device->flags.compatible_ids = 1; - - /* Presence of _RMV indicates 'removable' */ - status = acpi_get_handle(device->handle, "_RMV", &temp); - if (ACPI_SUCCESS(status)) - device->flags.removable = 1; - - /* Presence of _EJD|_EJ0 indicates 'ejectable' */ - status = acpi_get_handle(device->handle, "_EJD", &temp); - if (ACPI_SUCCESS(status)) - device->flags.ejectable = 1; - else { - status = acpi_get_handle(device->handle, "_EJ0", &temp); - if (ACPI_SUCCESS(status)) - device->flags.ejectable = 1; - } - - /* Presence of _LCK indicates 'lockable' */ - status = acpi_get_handle(device->handle, "_LCK", &temp); - if (ACPI_SUCCESS(status)) - device->flags.lockable = 1; - - /* Presence of _PS0|_PR0 indicates 'power manageable' */ - status = acpi_get_handle(device->handle, "_PS0", &temp); - if (ACPI_FAILURE(status)) - status = acpi_get_handle(device->handle, "_PR0", &temp); - if (ACPI_SUCCESS(status)) - device->flags.power_manageable = 1; - - /* TBD: Peformance management */ - - return_VALUE(0); -} - - -static int -acpi_bus_add ( - struct acpi_device **child, - struct acpi_device *parent, - acpi_handle handle, - int type) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_device *device = NULL; - char bus_id[5] = {'?',0}; - acpi_buffer buffer = {sizeof(bus_id), bus_id}; - acpi_device_info info; - char *hid = NULL; - char *uid = NULL; - int i = 0; - - ACPI_FUNCTION_TRACE("acpi_bus_add"); - - if (!child) - return_VALUE(-EINVAL); - - device = kmalloc(sizeof(struct acpi_device), GFP_KERNEL); - if (!device) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Memory allocation error\n")); - return_VALUE(-ENOMEM); - } - memset(device, 0, sizeof(struct acpi_device)); - - device->handle = handle; - device->parent = parent; - - memset(&info, 0, sizeof(acpi_device_info)); - - /* - * Bus ID - * ------ - * The device's Bus ID is simply the object name. - * TBD: Shouldn't this value be unique (within the ACPI namespace)? - */ - switch (type) { - case ACPI_BUS_TYPE_SYSTEM: - sprintf(device->pnp.bus_id, "%s", "ACPI"); - break; - case ACPI_BUS_TYPE_POWER_BUTTON: - sprintf(device->pnp.bus_id, "%s", "PWRF"); - break; - case ACPI_BUS_TYPE_SLEEP_BUTTON: - sprintf(device->pnp.bus_id, "%s", "SLPF"); - break; - default: - acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer); - /* Clean up trailing underscores (if any) */ - for (i = 3; i > 1; i--) { - if (bus_id[i] == '_') - bus_id[i] = '\0'; - else - break; - } - sprintf(device->pnp.bus_id, "%s", bus_id); - break; - } - - /* - * Flags - * ----- - * Get prior to calling acpi_bus_get_status() so we know whether - * or not _STA is present. Note that we only look for object - * handles -- cannot evaluate objects until we know the device is - * present and properly initialized. - */ - result = acpi_bus_get_flags(device); - if (0 != result) - goto end; - - /* - * Status - * ------ - * See if the device is present. We always assume that non-Device() - * objects (e.g. thermal zones, power resources, processors, etc.) are - * present, functioning, etc. (at least when parent object is present). - * Note that _STA has a different meaning for some objects (e.g. - * power resources) so we need to be careful how we use it. - */ - switch (type) { - case ACPI_BUS_TYPE_DEVICE: - result = acpi_bus_get_status(device); - if (0 != result) - goto end; - break; - default: - STRUCT_TO_INT(device->status) = 0x0F; - break; - } - if (!device->status.present) { - result = -ENOENT; - goto end; - } - - /* - * Initialize Device - * ----------------- - * TBD: Synch with Core's enumeration/initialization process. - */ - - /* - * Hardware ID, Unique ID, & Bus Address - * ------------------------------------- - */ - switch (type) { - case ACPI_BUS_TYPE_DEVICE: - status = acpi_get_object_info(handle, &info); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error reading device info\n")); - result = -ENODEV; - goto end; - } - /* Clean up info strings (not NULL terminated) */ - info.hardware_id[sizeof(info.hardware_id)-1] = '\0'; - info.unique_id[sizeof(info.unique_id)-1] = '\0'; - if (info.valid & ACPI_VALID_HID) - hid = info.hardware_id; - if (info.valid & ACPI_VALID_UID) - uid = info.unique_id; - if (info.valid & ACPI_VALID_ADR) { - device->pnp.bus_address = info.address; - device->flags.bus_address = 1; - } - break; - case ACPI_BUS_TYPE_POWER: - hid = ACPI_POWER_HID; - break; - case ACPI_BUS_TYPE_PROCESSOR: - hid = ACPI_PROCESSOR_HID; - break; - case ACPI_BUS_TYPE_SYSTEM: - hid = ACPI_SYSTEM_HID; - break; - case ACPI_BUS_TYPE_THERMAL: - hid = ACPI_THERMAL_HID; - break; - case ACPI_BUS_TYPE_POWER_BUTTON: - hid = ACPI_BUTTON_HID_POWERF; - break; - case ACPI_BUS_TYPE_SLEEP_BUTTON: - hid = ACPI_BUTTON_HID_SLEEPF; - break; - } - - /* - * \_SB - * ---- - * Fix for the system root bus device -- the only root-level device. - */ - if ((parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) { - hid = ACPI_BUS_HID; - sprintf(device->pnp.device_name, "%s", ACPI_BUS_DEVICE_NAME); - sprintf(device->pnp.device_class, "%s", ACPI_BUS_CLASS); - } - - if (hid) { - sprintf(device->pnp.hardware_id, "%s", hid); - device->flags.hardware_id = 1; - } - if (uid) { - sprintf(device->pnp.unique_id, "%s", uid); - device->flags.unique_id = 1; - } - - /* - * Power Management - * ---------------- - */ - if (device->flags.power_manageable) { - result = acpi_bus_get_power_flags(device); - if (0 != result) - goto end; - } - - /* - * Performance Management - * ---------------------- - */ - if (device->flags.performance_manageable) { - result = acpi_bus_get_perf_flags(device); - if (0 != result) - goto end; - } - - /* - * Context - * ------- - * Attach this 'struct acpi_device' to the ACPI object. This makes - * resolutions from handle->device very efficient. Note that we need - * to be careful with fixed-feature devices as they all attach to the - * root object. - */ - switch (type) { - case ACPI_BUS_TYPE_POWER_BUTTON: - case ACPI_BUS_TYPE_SLEEP_BUTTON: - break; - default: - status = acpi_attach_data(device->handle, - acpi_bus_data_handler, device); - break; - } - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error attaching device data\n")); - result = -ENODEV; - goto end; - } - - /* - * Linkage - * ------- - * Link this device to its parent and siblings. - */ - INIT_LIST_HEAD(&device->children); - if (!device->parent) - INIT_LIST_HEAD(&device->node); - else - list_add_tail(&device->node, &device->parent->children); - -#ifdef CONFIG_ACPI_DEBUG - { - char *type_string = NULL; - char name[80] = {'?','\0'}; - acpi_buffer buffer = {sizeof(name), name}; - - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); - - switch (type) { - case ACPI_BUS_TYPE_DEVICE: - type_string = "Device"; - break; - case ACPI_BUS_TYPE_POWER: - type_string = "Power Resource"; - break; - case ACPI_BUS_TYPE_PROCESSOR: - type_string = "Processor"; - break; - case ACPI_BUS_TYPE_SYSTEM: - type_string = "System"; - break; - case ACPI_BUS_TYPE_THERMAL: - type_string = "Thermal Zone"; - break; - case ACPI_BUS_TYPE_POWER_BUTTON: - type_string = "Power Button"; - sprintf(name, "PWRB"); - break; - case ACPI_BUS_TYPE_SLEEP_BUTTON: - type_string = "Sleep Button"; - sprintf(name, "SLPB"); - break; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s %s [%p]\n", - type_string, name, handle)); - } -#endif /*CONFIG_ACPI_DEBUG*/ - - /* - * Global Device Hierarchy: - * ------------------------ - * Register this device with the global device hierarchy. - */ - acpi_device_register(device, parent); - - /* - * Bind _ADR-Based Devices - * ----------------------- - * If there's a a bus address (_ADR) then we utilize the parent's - * 'bind' function (if exists) to bind the ACPI- and natively- - * enumerated device representations. - */ - if (device->flags.bus_address) { - if (device->parent && device->parent->ops.bind) - device->parent->ops.bind(device); - } - - /* - * Locate & Attach Driver - * ---------------------- - * If there's a hardware id (_HID) or compatible ids (_CID) we check - * to see if there's a driver installed for this kind of device. Note - * that drivers can install before or after a device in enumerated. - * - * TBD: Assumes LDM provides driver hot-plug capability. - */ - if (device->flags.hardware_id || device->flags.compatible_ids) - acpi_bus_find_driver(device); - -end: - if (0 != result) { - kfree(device); - return_VALUE(result); - } - - *child = device; - - return_VALUE(0); -} - - -static int -acpi_bus_remove ( - struct acpi_device *device, - int type) -{ - ACPI_FUNCTION_TRACE("acpi_bus_remove"); - - if (!device) - return_VALUE(-ENODEV); - - acpi_device_unregister(device); - - kfree(device); - - return_VALUE(0); -} - - -int -acpi_bus_scan ( - struct acpi_device *start) -{ - acpi_status status = AE_OK; - struct acpi_device *parent = NULL; - struct acpi_device *child = NULL; - acpi_handle phandle = 0; - acpi_handle chandle = 0; - acpi_object_type type = 0; - u32 level = 1; - - ACPI_FUNCTION_TRACE("acpi_bus_scan"); - - if (!start) - return_VALUE(-EINVAL); - - parent = start; - phandle = start->handle; - - /* - * Parse through the ACPI namespace, identify all 'devices', and - * create a new 'struct acpi_device' for each. - */ - while ((level > 0) && parent) { - - status = acpi_get_next_object(ACPI_TYPE_ANY, phandle, - chandle, &chandle); - - /* - * If this scope is exhausted then move our way back up. - */ - if (ACPI_FAILURE(status)) { - level--; - chandle = phandle; - acpi_get_parent(phandle, &phandle); - if (parent->parent) - parent = parent->parent; - continue; - } - - status = acpi_get_type(chandle, &type); - if (ACPI_FAILURE(status)) - continue; - - /* - * If this is a scope object then parse it (depth-first). - */ - if (type == ACPI_TYPE_ANY) { - /* Hack to get around scope identity problem */ - status = acpi_get_next_object(ACPI_TYPE_ANY, chandle, 0, NULL); - if (ACPI_SUCCESS(status)) { - level++; - phandle = chandle; - chandle = 0; - } - continue; - } - - /* - * We're only interested in objects that we consider 'devices'. - */ - switch (type) { - case ACPI_TYPE_DEVICE: - type = ACPI_BUS_TYPE_DEVICE; - break; - case ACPI_TYPE_PROCESSOR: - type = ACPI_BUS_TYPE_PROCESSOR; - break; - case ACPI_TYPE_THERMAL: - type = ACPI_BUS_TYPE_THERMAL; - break; - case ACPI_TYPE_POWER: - type = ACPI_BUS_TYPE_POWER; - break; - default: - continue; - } - - status = acpi_bus_add(&child, parent, chandle, type); - if (ACPI_FAILURE(status)) - continue; - - /* - * If the device is present, enabled, and functioning then - * parse its scope (depth-first). Note that we need to - * represent absent devices to facilitate PnP notifications - * -- but only the subtree head (not all of its children, - * which will be enumerated when the parent is inserted). - * - * TBD: Need notifications and other detection mechanisms - * in place before we can fully implement this. - */ - if (child->status.present) { - status = acpi_get_next_object(ACPI_TYPE_ANY, chandle, - 0, NULL); - if (ACPI_SUCCESS(status)) { - level++; - phandle = chandle; - chandle = 0; - parent = child; - } - } - } - - return_VALUE(0); -} - - -static int -acpi_bus_scan_fixed ( - struct acpi_device *root) -{ - int result = 0; - struct acpi_device *device = NULL; - - ACPI_FUNCTION_TRACE("acpi_bus_scan"); - - if (!root) - return_VALUE(-ENODEV); - - /* - * Enumerate all fixed-feature devices. - */ - if (acpi_fadt.pwr_button == 0) - result = acpi_bus_add(&device, acpi_root, - ACPI_ROOT_OBJECT, ACPI_BUS_TYPE_POWER_BUTTON); - - if (acpi_fadt.sleep_button == 0) - result = acpi_bus_add(&device, acpi_root, - ACPI_ROOT_OBJECT, ACPI_BUS_TYPE_SLEEP_BUTTON); - - return_VALUE(result); -} - - -/* -------------------------------------------------------------------------- - Initialization/Cleanup - -------------------------------------------------------------------------- */ - -int __init -acpi_blacklisted(void) -{ - int i = 0; - int blacklisted = 0; - acpi_table_header table_header; - - while (acpi_blacklist[i].oem_id[0] != '\0') - { - if (!ACPI_SUCCESS(acpi_get_table_header(acpi_blacklist[i].table, 1, &table_header))) { - i++; - continue; - } - - if (strncmp(acpi_blacklist[i].oem_id, table_header.oem_id, 6)) { - i++; - continue; - } - - if (strncmp(acpi_blacklist[i].oem_table_id, table_header.oem_table_id, 8)) { - i++; - continue; - } - - if ((acpi_blacklist[i].oem_revision_predicate == all_versions) - || (acpi_blacklist[i].oem_revision_predicate == less_than_or_equal - && table_header.oem_revision <= acpi_blacklist[i].oem_revision) - || (acpi_blacklist[i].oem_revision_predicate == greater_than_or_equal - && table_header.oem_revision >= acpi_blacklist[i].oem_revision) - || (acpi_blacklist[i].oem_revision_predicate == equal - && table_header.oem_revision == acpi_blacklist[i].oem_revision)) { - - printk(KERN_ERR PREFIX "Vendor \"%6.6s\" System \"%8.8s\" " - "Revision 0x%x has a known ACPI BIOS problem.\n", - acpi_blacklist[i].oem_id, - acpi_blacklist[i].oem_table_id, - acpi_blacklist[i].oem_revision); - - printk(KERN_ERR PREFIX "Reason: %s. This is a %s error\n", - acpi_blacklist[i].reason, - (acpi_blacklist[i].is_critical_error ? "non-recoverable" : "recoverable")); - - blacklisted = acpi_blacklist[i].is_critical_error; - break; - } - else { - i++; - } - } - - return blacklisted; -} - - -static int __init -acpi_bus_init_irq (void) -{ - int result = 0; - acpi_status status = AE_OK; - acpi_object arg = {ACPI_TYPE_INTEGER}; - acpi_object_list arg_list = {1, &arg}; - int irq_model = 0; - char *message = NULL; - - ACPI_FUNCTION_TRACE("acpi_bus_init_irq"); - - /* - * Let the system know what interrupt model we are using by - * evaluating the \_PIC object, if exists. - */ - result = acpi_get_interrupt_model(&irq_model); - if (0 != result) - return_VALUE(result); - - switch (irq_model) { - case ACPI_INT_MODEL_PIC: - message = "PIC"; - break; - case ACPI_INT_MODEL_IOAPIC: - message = "IOAPIC"; - break; - case ACPI_INT_MODEL_IOSAPIC: - message = "IOSAPIC"; - break; - default: - message = "UNKNOWN"; - break; - } - - printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message); - - arg.integer.value = irq_model; - - status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL); - if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PIC\n")); - return_VALUE(-ENODEV); - } - - return_VALUE(0); -} - - -static int __init -acpi_bus_init (void) -{ - int result = 0; - acpi_status status = AE_OK; - acpi_buffer buffer = {sizeof(acpi_fadt), &acpi_fadt}; - int progress = 0; - - ACPI_FUNCTION_TRACE("acpi_bus_init"); - - /* - * [0] Initailize the ACPI Core Subsystem. - */ - status = acpi_initialize_subsystem(); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Unable to initialize the ACPI Interpreter\n"); - result = -ENODEV; - goto end; - } - - progress++; - - /* - * [1] Load the ACPI tables. - */ - status = acpi_load_tables(); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Unable to load the System Description Tables\n"); - result = -ENODEV; - goto end; - } - - progress++; - - /* - * [2] Check the blacklist - */ - if (acpi_blacklisted()) { - result = -ENODEV; - goto end; - } - - progress++; - - /* - * [3] Get a separate copy of the FADT for use by other drivers. - */ - status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Unable to get the FADT\n"); - result = -ENODEV; - goto end; - } - - progress++; - - /* - * [4] Enable the ACPI Core Subsystem. - */ - status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Unable to start the ACPI Interpreter\n"); - result = -ENODEV; - goto end; - } - - printk(KERN_INFO PREFIX "Interpreter enabled\n"); - - progress++; - - /* - * [5] Register for all standard device notifications. - */ - result = acpi_bus_init_irq(); - if (0 != result) - goto end; - - /* - * [6] Register for all standard device notifications. - */ - status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Unable to register for device notifications\n"); - result = -ENODEV; - goto end; - } - - progress++; - - /* - * [7] Create the root device. - */ - result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, - ACPI_BUS_TYPE_SYSTEM); - if (0 != result) - goto end; - - progress++; - - /* - * [8] Create the root file system. - */ - acpi_device_dir(acpi_root) = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL); - if (!acpi_root) { - result = -ENODEV; - goto end; - } - acpi_root_dir = acpi_device_dir(acpi_root); - - progress++; - - /* - * [9] Install drivers required for proper enumeration of the - * ACPI namespace. - */ - acpi_system_init(); /* ACPI System */ - acpi_power_init(); /* ACPI Bus Power Management */ -#ifdef CONFIG_ACPI_EC - acpi_ec_init(); /* ACPI Embedded Controller */ -#endif -#ifdef CONFIG_ACPI_PCI - acpi_pci_link_init(); /* ACPI PCI Interrupt Link */ - acpi_pci_root_init(); /* ACPI PCI Root Bridge */ -#endif - progress++; - - /* - * [10] Enumerate devices in the ACPI namespace. - */ - - result = acpi_bus_scan_fixed(acpi_root); - if (0 != result) - goto end; - - result = acpi_bus_scan(acpi_root); - if (0 != result) - goto end; - -end: - if (0 != result) { - switch (progress) { - case 10: - case 9: remove_proc_entry("ACPI", NULL); - case 8: acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL); - case 7: acpi_remove_notify_handler(ACPI_ROOT_OBJECT, - ACPI_SYSTEM_NOTIFY, &acpi_bus_notify); - case 6: - case 5: - case 4: - case 3: - case 2: acpi_terminate(); - case 1: - case 0: - default: return_VALUE(-ENODEV); - } - } - - return_VALUE(0); -} - - -static void __exit -acpi_bus_exit (void) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE("acpi_bus_exit"); - - status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT, - ACPI_SYSTEM_NOTIFY, acpi_bus_notify); - if (ACPI_FAILURE(status)) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error removing notify handler\n")); - -#ifdef CONFIG_ACPI_PCI - acpi_pci_root_exit(); - acpi_pci_link_exit(); -#endif -#ifdef CONFIG_ACPI_EC - acpi_ec_exit(); -#endif - acpi_power_exit(); - acpi_system_exit(); - - acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL); - - remove_proc_entry(ACPI_BUS_FILE_ROOT, NULL); - - status = acpi_terminate(); - if (ACPI_FAILURE(status)) - printk(KERN_ERR PREFIX "Unable to terminate the ACPI Interpreter\n"); - else - printk(KERN_ERR PREFIX "Interpreter disabled\n"); - - return_VOID; -} - - -int __init -acpi_init (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_init"); - - printk(KERN_INFO PREFIX "Bus Driver revision %08x\n", - ACPI_DRIVER_VERSION); - printk(KERN_INFO PREFIX "Core Subsystem revision %08x\n", - ACPI_CA_VERSION); - - /* Initial core debug level excludes drivers, so include them now */ - acpi_set_debug(ACPI_DEBUG_LOW); - - if (acpi_disabled) { - printk(KERN_INFO PREFIX "Disabled via command line (acpi=off)\n"); - return -ENODEV; - } - -#ifdef CONFIG_PM - if (PM_IS_ACTIVE()) { - printk(KERN_INFO PREFIX "APM is already active, exiting\n"); - return -ENODEV; - } -#endif - - result = acpi_bus_init(); - if (0 != result) - return_VALUE(result); - -#ifdef CONFIG_PM - pm_active = 1; -#endif - - return_VALUE(0); -} - - -void __exit -acpi_exit (void) -{ - ACPI_FUNCTION_TRACE("acpi_exit"); - -#ifdef CONFIG_PM - pm_active = 0; -#endif - - acpi_bus_exit(); - - return_VOID; -} - - -int __init -acpi_setup(char *str) -{ - while (str && *str) { - if (strncmp(str, "off", 3) == 0) - acpi_disabled = 1; - str = strchr(str, ','); - if (str) - str += strspn(str, ", \t"); - } - return 1; -} - - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -subsys_initcall(acpi_init); -#endif - -__setup("acpi=", acpi_setup); - diff -Nru a/drivers/acpi/acpi_bus.h b/drivers/acpi/acpi_bus.h --- a/drivers/acpi/acpi_bus.h Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/acpi_bus.h Sun Jun 2 18:44:57 2002 @@ -1,5 +1,5 @@ /* - * acpi_bus.h - ACPI Bus Driver ($Revision: 19 $) + * acpi_bus.h - ACPI Bus Driver ($Revision: 21 $) * * Copyright (C) 2001, 2002 Andy Grover * Copyright (C) 2001, 2002 Paul Diefenbaugh @@ -56,9 +56,7 @@ #include #define ACPI_BUS_FILE_ROOT "acpi" - extern struct proc_dir_entry *acpi_root_dir; - extern FADT_DESCRIPTOR acpi_fadt; enum acpi_bus_removal_type { diff -Nru a/drivers/acpi/acpi_button.c b/drivers/acpi/acpi_button.c --- a/drivers/acpi/acpi_button.c Sun Jun 2 18:44:56 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,411 +0,0 @@ -/* - * acpi_button.c - ACPI Button Driver ($Revision: 24 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include "acpi_bus.h" -#include "acpi_drivers.h" - - -#define _COMPONENT ACPI_BUTTON_COMPONENT -ACPI_MODULE_NAME ("acpi_button") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME); -MODULE_LICENSE("GPL"); - -#define PREFIX "ACPI: " - - -int acpi_button_add (struct acpi_device *device); -int acpi_button_remove (struct acpi_device *device, int type); - -static struct acpi_driver acpi_button_driver = { - name: ACPI_BUTTON_DRIVER_NAME, - class: ACPI_BUTTON_CLASS, - ids: "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E", - ops: { - add: acpi_button_add, - remove: acpi_button_remove, - }, -}; - -struct acpi_button { - acpi_handle handle; - struct acpi_device *device; /* Fixed button kludge */ - u8 type; - unsigned long pushed; -}; - - -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -#include -#include - -static struct proc_dir_entry *acpi_button_dir = NULL; - - -static int -acpi_button_read_info ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_button *button = (struct acpi_button *) data; - char *p = page; - int len = 0; - - ACPI_FUNCTION_TRACE("acpi_button_read_info"); - - if (!button || !button->device) - goto end; - - p += sprintf(p, "type: %s\n", - acpi_device_name(button->device)); - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_button_add_fs ( - struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - struct acpi_button *button = NULL; - - ACPI_FUNCTION_TRACE("acpi_button_add_fs"); - - if (!device || !acpi_driver_data(device)) - return_VALUE(-EINVAL); - - button = acpi_driver_data(device); - - if (!acpi_button_dir) { - acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); - if (!acpi_button_dir) - return_VALUE(-ENODEV); - } - - switch (button->type) { - case ACPI_BUTTON_TYPE_POWER: - case ACPI_BUTTON_TYPE_POWERF: - entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, - acpi_button_dir); - break; - case ACPI_BUTTON_TYPE_SLEEP: - case ACPI_BUTTON_TYPE_SLEEPF: - entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, - acpi_button_dir); - break; - case ACPI_BUTTON_TYPE_LID: - entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, - acpi_button_dir); - break; - } - - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); - if (!acpi_device_dir(device)) - return_VALUE(-ENODEV); - - /* 'info' [R] */ - entry = create_proc_entry(ACPI_BUTTON_FILE_INFO, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_BUTTON_FILE_INFO)); - else { - entry->read_proc = acpi_button_read_info; - entry->data = acpi_driver_data(device); - } - - return_VALUE(0); -} - - -static int -acpi_button_remove_fs ( - struct acpi_device *device) -{ - ACPI_FUNCTION_TRACE("acpi_button_remove_fs"); - - if (!acpi_button_dir) - return_VALUE(-ENODEV); - - if (acpi_device_dir(device)) - remove_proc_entry(acpi_device_bid(device), acpi_button_dir); - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ - -void -acpi_button_notify ( - acpi_handle handle, - u32 event, - void *data) -{ - struct acpi_button *button = (struct acpi_button *) data; - - ACPI_FUNCTION_TRACE("acpi_button_notify"); - - if (!button || !button->device) - return_VOID; - - switch (event) { - case ACPI_BUTTON_NOTIFY_STATUS: - acpi_bus_generate_event(button->device, event, ++button->pushed); - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Unsupported event [0x%x]\n", event)); - break; - } - - return_VOID; -} - - -acpi_status -acpi_button_notify_fixed ( - void *data) -{ - struct acpi_button *button = (struct acpi_button *) data; - - ACPI_FUNCTION_TRACE("acpi_button_notify_fixed"); - - if (!button) - return_ACPI_STATUS(AE_BAD_PARAMETER); - - acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button); - - return_ACPI_STATUS(AE_OK); -} - - -int -acpi_button_add ( - struct acpi_device *device) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_button *button = NULL; - - ACPI_FUNCTION_TRACE("acpi_button_add"); - - if (!device) - return_VALUE(-EINVAL); - - button = kmalloc(sizeof(struct acpi_button), GFP_KERNEL); - if (!button) - return_VALUE(-ENOMEM); - memset(button, 0, sizeof(struct acpi_button)); - - button->device = device; - button->handle = device->handle; - acpi_driver_data(device) = button; - - /* - * Determine the button type (via hid), as fixed-feature buttons - * need to be handled a bit differently than generic-space. - */ - if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) { - button->type = ACPI_BUTTON_TYPE_POWER; - sprintf(acpi_device_name(device), "%s", - ACPI_BUTTON_DEVICE_NAME_POWER); - sprintf(acpi_device_class(device), "%s/%s", - ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); - } - else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) { - button->type = ACPI_BUTTON_TYPE_POWERF; - sprintf(acpi_device_name(device), "%s", - ACPI_BUTTON_DEVICE_NAME_POWERF); - sprintf(acpi_device_class(device), "%s/%s", - ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); - } - else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) { - button->type = ACPI_BUTTON_TYPE_SLEEP; - sprintf(acpi_device_name(device), "%s", - ACPI_BUTTON_DEVICE_NAME_SLEEP); - sprintf(acpi_device_class(device), "%s/%s", - ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); - } - else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) { - button->type = ACPI_BUTTON_TYPE_SLEEPF; - sprintf(acpi_device_name(device), "%s", - ACPI_BUTTON_DEVICE_NAME_SLEEPF); - sprintf(acpi_device_class(device), "%s/%s", - ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); - } - else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) { - button->type = ACPI_BUTTON_TYPE_LID; - sprintf(acpi_device_name(device), "%s", - ACPI_BUTTON_DEVICE_NAME_LID); - sprintf(acpi_device_class(device), "%s/%s", - ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID); - } - else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unsupported hid [%s]\n", - acpi_device_hid(device))); - result = -ENODEV; - goto end; - } - - result = acpi_button_add_fs(device); - if (0 != result) - goto end; - - switch (button->type) { - case ACPI_BUTTON_TYPE_POWERF: - status = acpi_install_fixed_event_handler ( - ACPI_EVENT_POWER_BUTTON, - acpi_button_notify_fixed, - button); - break; - case ACPI_BUTTON_TYPE_SLEEPF: - status = acpi_install_fixed_event_handler ( - ACPI_EVENT_SLEEP_BUTTON, - acpi_button_notify_fixed, - button); - break; - default: - status = acpi_install_notify_handler ( - button->handle, - ACPI_DEVICE_NOTIFY, - acpi_button_notify, - button); - break; - } - - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error installing notify handler\n")); - result = -ENODEV; - goto end; - } - - printk(KERN_INFO PREFIX "%s [%s]\n", - acpi_device_name(device), acpi_device_bid(device)); - -end: - if (0 != result) { - acpi_button_remove_fs(device); - kfree(button); - } - - return_VALUE(result); -} - - -int -acpi_button_remove (struct acpi_device *device, int type) -{ - acpi_status status = 0; - struct acpi_button *button = NULL; - - ACPI_FUNCTION_TRACE("acpi_button_remove"); - - if (!device || !acpi_driver_data(device)) - return_VALUE(-EINVAL); - - button = acpi_driver_data(device); - - /* Unregister for device notifications. */ - switch (button->type) { - case ACPI_BUTTON_TYPE_POWERF: - status = acpi_remove_fixed_event_handler( - ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed); - break; - case ACPI_BUTTON_TYPE_SLEEPF: - status = acpi_remove_fixed_event_handler( - ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed); - break; - default: - status = acpi_remove_notify_handler(button->handle, - ACPI_DEVICE_NOTIFY, acpi_button_notify); - break; - } - - if (ACPI_FAILURE(status)) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error removing notify handler\n")); - - acpi_button_remove_fs(device); - - kfree(button); - - return_VALUE(0); -} - - -static int __init -acpi_button_init (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_button_init"); - - result = acpi_bus_register_driver(&acpi_button_driver); - if (0 > result) - return_VALUE(-ENODEV); - - return_VALUE(0); -} - - -static void __exit -acpi_button_exit (void) -{ - ACPI_FUNCTION_TRACE("acpi_button_exit"); - - acpi_bus_unregister_driver(&acpi_button_driver); - - return_VOID; -} - - -module_init(acpi_button_init); -module_exit(acpi_button_exit); diff -Nru a/drivers/acpi/acpi_drivers.h b/drivers/acpi/acpi_drivers.h --- a/drivers/acpi/acpi_drivers.h Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/acpi_drivers.h Sun Jun 2 18:44:58 2002 @@ -1,5 +1,5 @@ /* - * acpi_drivers.h ($Revision: 23 $) + * acpi_drivers.h ($Revision: 29 $) * * Copyright (C) 2001, 2002 Andy Grover * Copyright (C) 2001, 2002 Paul Diefenbaugh @@ -30,7 +30,6 @@ #include "acpi_bus.h" -#define ACPI_DRIVER_VERSION 0x20020404 #define ACPI_MAX_STRING 80 @@ -148,41 +147,53 @@ PCI -------------------------------------------------------------------------- */ -#define ACPI_PCI_LINK_COMPONENT 0x00400000 -#define ACPI_PCI_LINK_CLASS "irq_routing" -#define ACPI_PCI_LINK_HID "PNP0C0F" -#define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver" -#define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link" -#define ACPI_PCI_LINK_FILE_INFO "info" -#define ACPI_PCI_LINK_FILE_STATUS "state" +#ifdef CONFIG_ACPI_PCI -#define ACPI_PCI_ROOT_COMPONENT 0x00800000 -#define ACPI_PCI_ROOT_CLASS "bridge" +#define ACPI_PCI_COMPONENT 0x00400000 + +/* ACPI PCI Root Bridge (pci_root.c) */ + +#define ACPI_PCI_ROOT_CLASS "pci_bridge" #define ACPI_PCI_ROOT_HID "PNP0A03" #define ACPI_PCI_ROOT_DRIVER_NAME "ACPI PCI Root Bridge Driver" #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" -#define ACPI_PCI_PRT_DEVICE_NAME "PCI Interrupt Routing Table" +int acpi_pci_root_init (void); +void acpi_pci_root_exit (void); -#ifdef CONFIG_ACPI_PCI +/* ACPI PCI Interrupt Link (pci_link.c) */ +#define ACPI_PCI_LINK_CLASS "pci_irq_routing" +#define ACPI_PCI_LINK_HID "PNP0C0F" +#define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver" +#define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link" +#define ACPI_PCI_LINK_FILE_INFO "info" +#define ACPI_PCI_LINK_FILE_STATUS "state" -int acpi_pci_link_get_irq (struct acpi_prt_entry *entry, int *irq); -int acpi_pci_link_set_irq (struct acpi_prt_entry *entry, int irq); +int acpi_pci_link_check (void); +int acpi_pci_link_get_irq (acpi_handle handle, int index); int acpi_pci_link_init (void); void acpi_pci_link_exit (void); -int acpi_pci_root_init (void); -void acpi_pci_root_exit (void); +/* ACPI PCI Interrupt Routing (pci_irq.c) */ -#endif +int acpi_pci_irq_add_prt (acpi_handle handle, int segment, int bus); + +/* ACPI PCI Device Binding (pci_bind.c) */ + +struct pci_bus; + +int acpi_pci_bind (struct acpi_device *device); +int acpi_pci_bind_root (struct acpi_device *device, acpi_pci_id *id, struct pci_bus *bus); + +#endif /*CONFIG_ACPI_PCI*/ /* -------------------------------------------------------------------------- Power Resource -------------------------------------------------------------------------- */ -#define ACPI_POWER_COMPONENT 0x01000000 +#define ACPI_POWER_COMPONENT 0x00800000 #define ACPI_POWER_CLASS "power_resource" #define ACPI_POWER_HID "ACPI_PWR" #define ACPI_POWER_DRIVER_NAME "ACPI Power Resource Driver" @@ -207,7 +218,7 @@ Processor -------------------------------------------------------------------------- */ -#define ACPI_PROCESSOR_COMPONENT 0x02000000 +#define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" #define ACPI_PROCESSOR_HID "ACPI_CPU" #define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" @@ -230,7 +241,7 @@ System -------------------------------------------------------------------------- */ -#define ACPI_SYSTEM_COMPONENT 0x04000000 +#define ACPI_SYSTEM_COMPONENT 0x02000000 #define ACPI_SYSTEM_CLASS "system" #define ACPI_SYSTEM_HID "ACPI_SYS" #define ACPI_SYSTEM_DRIVER_NAME "ACPI System Driver" @@ -256,7 +267,7 @@ Thermal Zone -------------------------------------------------------------------------- */ -#define ACPI_THERMAL_COMPONENT 0x08000000 +#define ACPI_THERMAL_COMPONENT 0x04000000 #define ACPI_THERMAL_CLASS "thermal_zone" #define ACPI_THERMAL_HID "ACPI_THM" #define ACPI_THERMAL_DRIVER_NAME "ACPI Thermal Zone Driver" diff -Nru a/drivers/acpi/acpi_ec.c b/drivers/acpi/acpi_ec.c --- a/drivers/acpi/acpi_ec.c Sun Jun 2 18:44:57 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,736 +0,0 @@ -/* - * acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 28 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include "acpi_bus.h" -#include "acpi_drivers.h" - - -#define _COMPONENT ACPI_EC_COMPONENT -ACPI_MODULE_NAME ("acpi_ec") - -#define PREFIX "ACPI: " - - -#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ -#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ -#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ - -#define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */ -#define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */ - -#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ -#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ -#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ - -#define ACPI_EC_COMMAND_READ 0x80 -#define ACPI_EC_COMMAND_WRITE 0x81 -#define ACPI_EC_COMMAND_QUERY 0x84 - -static int acpi_ec_add (struct acpi_device *device); -static int acpi_ec_remove (struct acpi_device *device, int type); -static int acpi_ec_start (struct acpi_device *device); -static int acpi_ec_stop (struct acpi_device *device, int type); - -static struct acpi_driver acpi_ec_driver = { - name: ACPI_EC_DRIVER_NAME, - class: ACPI_EC_CLASS, - ids: ACPI_EC_HID, - ops: { - add: acpi_ec_add, - remove: acpi_ec_remove, - start: acpi_ec_start, - stop: acpi_ec_stop, - }, -}; - -struct acpi_ec { - acpi_handle handle; - unsigned long gpe_bit; - unsigned long status_port; - unsigned long command_port; - unsigned long data_port; - unsigned long global_lock; - spinlock_t lock; -}; - - -/* -------------------------------------------------------------------------- - Transaction Management - -------------------------------------------------------------------------- */ - -static int -acpi_ec_wait ( - struct acpi_ec *ec, - u8 event) -{ - u8 acpi_ec_status = 0; - u32 i = ACPI_EC_UDELAY_COUNT; - - if (!ec) - return -EINVAL; - - /* Poll the EC status register waiting for the event to occur. */ - switch (event) { - case ACPI_EC_EVENT_OBF: - do { - acpi_ec_status = inb(ec->status_port); - if (acpi_ec_status & ACPI_EC_FLAG_OBF) - return 0; - udelay(ACPI_EC_UDELAY); - } while (--i>0); - break; - case ACPI_EC_EVENT_IBE: - do { - acpi_ec_status = inb(ec->status_port); - if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) - return 0; - udelay(ACPI_EC_UDELAY); - } while (--i>0); - break; - default: - return -EINVAL; - } - - return -ETIME; -} - - -static int -acpi_ec_read ( - struct acpi_ec *ec, - u8 address, - u8 *data) -{ - acpi_status status = AE_OK; - int result = 0; - unsigned long flags = 0; - u32 glk = 0; - - ACPI_FUNCTION_TRACE("acpi_ec_read"); - - if (!ec || !data) - return_VALUE(-EINVAL); - - *data = 0; - - if (ec->global_lock) { - status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - } - - spin_lock_irqsave(&ec->lock, flags); - - outb(ACPI_EC_COMMAND_READ, ec->command_port); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (0 != result) - goto end; - - outb(address, ec->data_port); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (0 != result) - goto end; - - *data = inb(ec->data_port); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", - *data, address)); - -end: - spin_unlock_irqrestore(&ec->lock, flags); - - if (ec->global_lock) - acpi_release_global_lock(glk); - - return_VALUE(result); -} - - -static int -acpi_ec_write ( - struct acpi_ec *ec, - u8 address, - u8 data) -{ - int result = 0; - acpi_status status = AE_OK; - unsigned long flags = 0; - u32 glk = 0; - - ACPI_FUNCTION_TRACE("acpi_ec_write"); - - if (!ec) - return_VALUE(-EINVAL); - - if (ec->global_lock) { - status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - } - - spin_lock_irqsave(&ec->lock, flags); - - outb(ACPI_EC_COMMAND_WRITE, ec->command_port); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (0 != result) - goto end; - - outb(address, ec->data_port); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (0 != result) - goto end; - - outb(data, ec->data_port); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - if (0 != result) - goto end; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", - data, address)); - -end: - spin_unlock_irqrestore(&ec->lock, flags); - - if (ec->global_lock) - acpi_release_global_lock(glk); - - return_VALUE(result); -} - - -static int -acpi_ec_query ( - struct acpi_ec *ec, - u8 *data) -{ - int result = 0; - acpi_status status = AE_OK; - unsigned long flags = 0; - u32 glk = 0; - - ACPI_FUNCTION_TRACE("acpi_ec_query"); - - if (!ec || !data) - return_VALUE(-EINVAL); - - *data = 0; - - if (ec->global_lock) { - status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - } - - /* - * Query the EC to find out which _Qxx method we need to evaluate. - * Note that successful completion of the query causes the ACPI_EC_SCI - * bit to be cleared (and thus clearing the interrupt source). - */ - - spin_lock_irqsave(&ec->lock, flags); - - outb(ACPI_EC_COMMAND_QUERY, ec->command_port); - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (0 != result) - goto end; - - *data = inb(ec->data_port); - if (!*data) - result = -ENODATA; - -end: - spin_unlock_irqrestore(&ec->lock, flags); - - if (ec->global_lock) - acpi_release_global_lock(glk); - - return_VALUE(result); -} - - -/* -------------------------------------------------------------------------- - Event Management - -------------------------------------------------------------------------- */ - -struct acpi_ec_query_data { - acpi_handle handle; - u8 data; -}; - - -static void -acpi_ec_gpe_query ( - void *data) -{ - struct acpi_ec_query_data *query_data = NULL; - static char object_name[5] = {'_','Q','0','0','\0'}; - const char hex[] = {'0','1','2','3','4','5','6','7', - '8','9','A','B','C','D','E','F'}; - - ACPI_FUNCTION_TRACE("acpi_ec_gpe_query"); - - if (!data) - return; - - query_data = (struct acpi_ec_query_data *) data; - - object_name[2] = hex[((query_data->data >> 4) & 0x0F)]; - object_name[3] = hex[(query_data->data & 0x0F)]; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); - - acpi_evaluate(query_data->handle, object_name, NULL, NULL); - - kfree(query_data); - - return; -} - - -static void -acpi_ec_gpe_handler ( - void *data) -{ - acpi_status status = AE_OK; - struct acpi_ec *ec = (struct acpi_ec *) data; - u8 value = 0; - unsigned long flags = 0; - struct acpi_ec_query_data *query_data = NULL; - - if (!ec) - return; - - spin_lock_irqsave(&ec->lock, flags); - value = inb(ec->command_port); - spin_unlock_irqrestore(&ec->lock, flags); - - /* TBD: Implement asynch events! - * NOTE: All we care about are EC-SCI's. Other EC events are - * handled via polling (yuck!). This is because some systems - * treat EC-SCIs as level (versus EDGE!) triggered, preventing - * a purely interrupt-driven approach (grumble, grumble). - */ - - if (!(value & ACPI_EC_FLAG_SCI)) - return; - - if (0 != acpi_ec_query(ec, &value)) - return; - - query_data = kmalloc(sizeof(struct acpi_ec_query_data), GFP_ATOMIC); - if (!query_data) - return; - query_data->handle = ec->handle; - query_data->data = value; - - status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, - acpi_ec_gpe_query, query_data); - if (ACPI_FAILURE(status)) - kfree(query_data); - - return; -} - - -/* -------------------------------------------------------------------------- - Address Space Management - -------------------------------------------------------------------------- */ - -static acpi_status -acpi_ec_space_setup ( - acpi_handle region_handle, - u32 function, - void *handler_context, - void **return_context) -{ - /* - * The EC object is in the handler context and is needed - * when calling the acpi_ec_space_handler. - */ - *return_context = handler_context; - - return AE_OK; -} - - -static acpi_status -acpi_ec_space_handler ( - u32 function, - ACPI_PHYSICAL_ADDRESS address, - u32 bit_width, - acpi_integer *value, - void *handler_context, - void *region_context) -{ - int result = 0; - struct acpi_ec *ec = NULL; - - ACPI_FUNCTION_TRACE("acpi_ec_space_handler"); - - if ((address > 0xFF) || (bit_width != 8) || !value || !handler_context) - return_VALUE(AE_BAD_PARAMETER); - - ec = (struct acpi_ec *) handler_context; - - switch (function) { - case ACPI_READ: - result = acpi_ec_read(ec, (u8) address, (u8*) value); - break; - case ACPI_WRITE: - result = acpi_ec_write(ec, (u8) address, (u8) *value); - break; - default: - result = -EINVAL; - break; - } - - switch (result) { - case -EINVAL: - return_VALUE(AE_BAD_PARAMETER); - break; - case -ENODEV: - return_VALUE(AE_NOT_FOUND); - break; - case -ETIME: - return_VALUE(AE_TIME); - break; - default: - return_VALUE(AE_OK); - } - -} - - -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -#include -#include - -struct proc_dir_entry *acpi_ec_dir = NULL; - - -static int -acpi_ec_read_info ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_ec *ec = (struct acpi_ec *) data; - char *p = page; - int len = 0; - - ACPI_FUNCTION_TRACE("acpi_ec_read_info"); - - if (!ec || (off != 0)) - goto end; - - p += sprintf(p, "gpe bit: 0x%02x\n", - (u32) ec->gpe_bit); - p += sprintf(p, "ports: 0x%02x, 0x%02x\n", - (u32) ec->status_port, (u32) ec->data_port); - p += sprintf(p, "use global lock: %s\n", - ec->global_lock?"yes":"no"); - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_ec_add_fs ( - struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - - ACPI_FUNCTION_TRACE("acpi_ec_add_fs"); - - if (!acpi_ec_dir) { - acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir); - if (!acpi_ec_dir) - return_VALUE(-ENODEV); - } - - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_ec_dir); - if (!acpi_device_dir(device)) - return_VALUE(-ENODEV); - } - - entry = create_proc_read_entry(ACPI_EC_FILE_INFO, S_IRUGO, - acpi_device_dir(device), acpi_ec_read_info, - acpi_driver_data(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Unable to create '%s' fs entry\n", - ACPI_EC_FILE_INFO)); - - return_VALUE(0); -} - - -static int -acpi_ec_remove_fs ( - struct acpi_device *device) -{ - ACPI_FUNCTION_TRACE("acpi_ec_remove_fs"); - - if (!acpi_ec_dir) - return_VALUE(-ENODEV); - - if (acpi_device_dir(device)) - remove_proc_entry(acpi_device_bid(device), acpi_ec_dir); - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ - -static int -acpi_ec_add ( - struct acpi_device *device) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_ec *ec = NULL; - - ACPI_FUNCTION_TRACE("acpi_ec_add"); - - if (!device) - return_VALUE(-EINVAL); - - ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); - if (!ec) - return_VALUE(-ENOMEM); - memset(ec, 0, sizeof(struct acpi_ec)); - - ec->handle = device->handle; - ec->lock = SPIN_LOCK_UNLOCKED; - sprintf(acpi_device_name(device), "%s", ACPI_EC_DEVICE_NAME); - sprintf(acpi_device_class(device), "%s", ACPI_EC_CLASS); - acpi_driver_data(device) = ec; - - /* Use the global lock for all EC transactions? */ - acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock); - - /* Get GPE bit assignment (EC events). */ - status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe_bit); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error obtaining GPE bit assignment\n")); - result = -ENODEV; - goto end; - } - - result = acpi_ec_add_fs(device); - if (0 != result) - goto end; - - printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", - acpi_device_name(device), acpi_device_bid(device), - (u32) ec->gpe_bit); - -end: - if (0 != result) - kfree(ec); - - return_VALUE(result); -} - - -static int -acpi_ec_remove ( - struct acpi_device *device, - int type) -{ - struct acpi_ec *ec = NULL; - - ACPI_FUNCTION_TRACE("acpi_ec_remove"); - - if (!device) - return_VALUE(-EINVAL); - - ec = (struct acpi_ec *) acpi_driver_data(device); - - acpi_ec_remove_fs(device); - - kfree(ec); - - return_VALUE(0); -} - - -static int -acpi_ec_start ( - struct acpi_device *device) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_ec *ec = NULL; - acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_resource *resource = NULL; - - ACPI_FUNCTION_TRACE("acpi_ec_start"); - - if (!device) - return_VALUE(-EINVAL); - - ec = (struct acpi_ec *) acpi_driver_data(device); - - if (!ec) - return_VALUE(-EINVAL); - - /* - * Get I/O port addresses - */ - - status = acpi_get_current_resources(ec->handle, &buffer); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses")); - return_VALUE(-ENODEV); - } - - resource = (acpi_resource *) buffer.pointer; - if (!resource || (resource->id != ACPI_RSTYPE_IO)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid or missing resource\n")); - result = -ENODEV; - goto end; - } - ec->data_port = resource->data.io.min_base_address; - - resource = ACPI_NEXT_RESOURCE(resource); - if (!resource || (resource->id != ACPI_RSTYPE_IO)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid or missing resource\n")); - result = -ENODEV; - goto end; - } - ec->command_port = ec->status_port = resource->data.io.min_base_address; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n", - (u32) ec->gpe_bit, (u32) ec->command_port, (u32) ec->data_port)); - - /* - * Install GPE handler - */ - - status = acpi_install_gpe_handler(ec->gpe_bit, - ACPI_EVENT_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - status = acpi_install_address_space_handler (ec->handle, - ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, - &acpi_ec_space_setup, ec); - if (ACPI_FAILURE(status)) { - acpi_remove_address_space_handler(ec->handle, - ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); - return_VALUE(-ENODEV); - } -end: - kfree(buffer.pointer); - - return_VALUE(result); -} - - -static int -acpi_ec_stop ( - struct acpi_device *device, - int type) -{ - acpi_status status = AE_OK; - struct acpi_ec *ec = NULL; - - ACPI_FUNCTION_TRACE("acpi_ec_stop"); - - if (!device) - return_VALUE(-EINVAL); - - ec = (struct acpi_ec *) acpi_driver_data(device); - - status = acpi_remove_address_space_handler(ec->handle, - ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - status = acpi_remove_gpe_handler(ec->gpe_bit, &acpi_ec_gpe_handler); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - return_VALUE(0); -} - - -int __init -acpi_ec_init (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_ec_init"); - - result = acpi_bus_register_driver(&acpi_ec_driver); - if (0 > result) { - remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir); - return_VALUE(-ENODEV); - } - - return_VALUE(0); -} - - -void __exit -acpi_ec_exit (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_ec_exit"); - - result = acpi_bus_unregister_driver(&acpi_ec_driver); - if (0 == result) - remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir); - - return_VOID; -} diff -Nru a/drivers/acpi/acpi_fan.c b/drivers/acpi/acpi_fan.c --- a/drivers/acpi/acpi_fan.c Sun Jun 2 18:44:56 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,300 +0,0 @@ -/* - * acpi_fan.c - ACPI Fan Driver ($Revision: 25 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include "acpi_bus.h" -#include "acpi_drivers.h" - - -#define _COMPONENT ACPI_FAN_COMPONENT -ACPI_MODULE_NAME ("acpi_fan") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME); -MODULE_LICENSE("GPL"); - -#define PREFIX "ACPI: " - - -int acpi_fan_add (struct acpi_device *device); -int acpi_fan_remove (struct acpi_device *device, int type); - -static struct acpi_driver acpi_fan_driver = { - name: ACPI_FAN_DRIVER_NAME, - class: ACPI_FAN_CLASS, - ids: ACPI_FAN_HID, - ops: { - add: acpi_fan_add, - remove: acpi_fan_remove, - }, -}; - -struct acpi_fan { - acpi_handle handle; -}; - - -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -#include -#include - -struct proc_dir_entry *acpi_fan_dir = NULL; - - -static int -acpi_fan_read_state ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_fan *fan = (struct acpi_fan *) data; - char *p = page; - int len = 0; - int state = 0; - - ACPI_FUNCTION_TRACE("acpi_fan_read_state"); - - if (!fan || (off != 0)) - goto end; - - if (0 != acpi_bus_get_power(fan->handle, &state)) - goto end; - - p += sprintf(p, "status: %s\n", - !state?"on":"off"); - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_fan_write_state ( - struct file *file, - const char *buffer, - unsigned long count, - void *data) -{ - int result = 0; - struct acpi_fan *fan = (struct acpi_fan *) data; - char state_string[12] = {'\0'}; - - ACPI_FUNCTION_TRACE("acpi_fan_write_state"); - - if (!fan || (count > sizeof(state_string) - 1)) - return_VALUE(-EINVAL); - - if (copy_from_user(state_string, buffer, count)) - return_VALUE(-EFAULT); - - state_string[count] = '\0'; - - result = acpi_bus_set_power(fan->handle, - simple_strtoul(state_string, NULL, 0)); - if (0 != result) - return_VALUE(result); - - return_VALUE(count); -} - - -static int -acpi_fan_add_fs ( - struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - - ACPI_FUNCTION_TRACE("acpi_fan_add_fs"); - - if (!device) - return_VALUE(-EINVAL); - - if (!acpi_fan_dir) { - acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir); - if (!acpi_fan_dir) - return_VALUE(-ENODEV); - } - - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_fan_dir); - if (!acpi_device_dir(device)) - return_VALUE(-ENODEV); - } - - /* 'status' [R/W] */ - entry = create_proc_entry(ACPI_FAN_FILE_STATE, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_FAN_FILE_STATE)); - else { - entry->read_proc = acpi_fan_read_state; - entry->write_proc = acpi_fan_write_state; - entry->data = acpi_driver_data(device); - } - - return_VALUE(0); -} - - -static int -acpi_fan_remove_fs ( - struct acpi_device *device) -{ - ACPI_FUNCTION_TRACE("acpi_fan_remove_fs"); - - if (!acpi_fan_dir) - return_VALUE(-ENODEV); - - if (acpi_device_dir(device)) - remove_proc_entry(acpi_device_bid(device), acpi_fan_dir); - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ - -int -acpi_fan_add ( - struct acpi_device *device) -{ - int result = 0; - struct acpi_fan *fan = NULL; - int state = 0; - - ACPI_FUNCTION_TRACE("acpi_fan_add"); - - if (!device) - return_VALUE(-EINVAL); - - fan = kmalloc(sizeof(struct acpi_fan), GFP_KERNEL); - if (!fan) - return_VALUE(-ENOMEM); - memset(fan, 0, sizeof(struct acpi_fan)); - - fan->handle = device->handle; - sprintf(acpi_device_name(device), "%s", ACPI_FAN_DEVICE_NAME); - sprintf(acpi_device_class(device), "%s", ACPI_FAN_CLASS); - acpi_driver_data(device) = fan; - - result = acpi_bus_get_power(fan->handle, &state); - if (0 != result) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error reading power state\n")); - goto end; - } - - result = acpi_fan_add_fs(device); - if (0 != result) - goto end; - - printk(KERN_INFO PREFIX "%s [%s] (%s)\n", - acpi_device_name(device), acpi_device_bid(device), - !device->power.state?"on":"off"); - -end: - if (0 != result) - kfree(fan); - - return_VALUE(result); -} - - -int -acpi_fan_remove ( - struct acpi_device *device, - int type) -{ - struct acpi_fan *fan = NULL; - - ACPI_FUNCTION_TRACE("acpi_fan_remove"); - - if (!device || !acpi_driver_data(device)) - return_VALUE(-EINVAL); - - fan = (struct acpi_fan *) acpi_driver_data(device); - - acpi_fan_remove_fs(device); - - kfree(fan); - - return_VALUE(0); -} - - -int __init -acpi_fan_init (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_fan_init"); - - result = acpi_bus_register_driver(&acpi_fan_driver); - if (0 > result) - return_VALUE(-ENODEV); - - return_VALUE(0); -} - - -void __exit -acpi_fan_exit (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_fan_exit"); - - result = acpi_bus_unregister_driver(&acpi_fan_driver); - if (0 == result) - remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir); - - return_VOID; -} - - -module_init(acpi_fan_init); -module_exit(acpi_fan_exit); - diff -Nru a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c --- a/drivers/acpi/acpi_ksyms.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/acpi_ksyms.c Sun Jun 2 18:44:57 2002 @@ -1,5 +1,5 @@ /* - * acpi_ksyms.c - ACPI Kernel Symbols ($Revision: 13 $) + * acpi_ksyms.c - ACPI Kernel Symbols ($Revision: 15 $) * * Copyright (C) 2001, 2002 Andy Grover * Copyright (C) 2001, 2002 Paul Diefenbaugh @@ -80,9 +80,9 @@ EXPORT_SYMBOL(acpi_clear_event); EXPORT_SYMBOL(acpi_get_timer_duration); EXPORT_SYMBOL(acpi_get_timer); -EXPORT_SYMBOL(acpi_hw_get_sleep_type_data); -EXPORT_SYMBOL(acpi_hw_bit_register_read); -EXPORT_SYMBOL(acpi_hw_bit_register_write); +EXPORT_SYMBOL(acpi_get_sleep_type_data); +EXPORT_SYMBOL(acpi_get_register); +EXPORT_SYMBOL(acpi_set_register); EXPORT_SYMBOL(acpi_enter_sleep_state); EXPORT_SYMBOL(acpi_get_system_info); diff -Nru a/drivers/acpi/acpi_osl.c b/drivers/acpi/acpi_osl.c --- a/drivers/acpi/acpi_osl.c Sun Jun 2 18:44:58 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,833 +0,0 @@ -/* - * acpi_osl.c - OS-dependent functions ($Revision: 69 $) - * - * Copyright (C) 2000 Andrew Henroid - * Copyright (C) 2001 Andrew Grover - * Copyright (C) 2001 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "acpi.h" - -#ifdef CONFIG_ACPI_EFI -#include -#endif - -#ifdef _IA64 -#include -#include -#endif - - -#define _COMPONENT ACPI_OS_SERVICES -ACPI_MODULE_NAME ("osl") - -#define PREFIX "ACPI: " - -typedef struct -{ - OSD_EXECUTION_CALLBACK function; - void *context; -} ACPI_OS_DPC; - - -#ifdef ENABLE_DEBUGGER -#include -/* stuff for debugger support */ -int acpi_in_debugger = 0; -extern NATIVE_CHAR line_buf[80]; -#endif /*ENABLE_DEBUGGER*/ - -static int acpi_irq_irq = 0; -static OSD_HANDLER acpi_irq_handler = NULL; -static void *acpi_irq_context = NULL; - - -acpi_status -acpi_os_initialize(void) -{ - /* - * Initialize PCI configuration space access, as we'll need to access - * it while walking the namespace (bus 0 and root bridges w/ _BBNs). - */ -#if 0 - pcibios_config_init(); - if (!pci_config_read || !pci_config_write) { - printk(KERN_ERR PREFIX "Access to PCI configuration space unavailable\n"); - return AE_NULL_ENTRY; - } -#endif - return AE_OK; -} - -acpi_status -acpi_os_terminate(void) -{ - if (acpi_irq_handler) { - acpi_os_remove_interrupt_handler(acpi_irq_irq, - acpi_irq_handler); - } - - return AE_OK; -} - -void -acpi_os_printf(const NATIVE_CHAR *fmt,...) -{ - va_list args; - va_start(args, fmt); - acpi_os_vprintf(fmt, args); - va_end(args); -} - -void -acpi_os_vprintf(const NATIVE_CHAR *fmt, va_list args) -{ - static char buffer[512]; - - vsprintf(buffer, fmt, args); - -#ifdef ENABLE_DEBUGGER - if (acpi_in_debugger) { - kdb_printf("%s", buffer); - } else { - printk("%s", buffer); - } -#else - printk("%s", buffer); -#endif -} - -void * -acpi_os_allocate(ACPI_SIZE size) -{ - return kmalloc(size, GFP_KERNEL); -} - -void * -acpi_os_callocate(ACPI_SIZE size) -{ - void *ptr = acpi_os_allocate(size); - if (ptr) - memset(ptr, 0, size); - - return ptr; -} - -void -acpi_os_free(void *ptr) -{ - kfree(ptr); -} - - -acpi_status -acpi_os_get_root_pointer(u32 flags, ACPI_POINTER *addr) -{ -#ifndef CONFIG_ACPI_EFI - if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) { - printk(KERN_ERR PREFIX "System description tables not found\n"); - return AE_NOT_FOUND; - } -#else /*CONFIG_ACPI_EFI*/ - addr->pointer_type = ACPI_PHYSICAL_POINTER; - if (efi.acpi20) - addr->pointer.physical = (ACPI_PHYSICAL_ADDRESS) efi.acpi20; - else if (efi.acpi) - addr->pointer.physical = (ACPI_PHYSICAL_ADDRESS) efi.acpi; - else { - printk(KERN_ERR PREFIX "System description tables not found\n"); - addr->pointer.physical = 0; - return AE_NOT_FOUND; - } -#endif /*CONFIG_ACPI_EFI*/ - - return AE_OK; -} - -acpi_status -acpi_os_map_memory(ACPI_PHYSICAL_ADDRESS phys, ACPI_SIZE size, void **virt) -{ - if (phys > ULONG_MAX) { - printk(KERN_ERR PREFIX "Cannot map memory that high\n"); - return AE_BAD_PARAMETER; - } - - /* - * ioremap already checks to ensure this is in reserved space - */ - *virt = ioremap((unsigned long) phys, size); - if (!*virt) - return AE_NO_MEMORY; - - return AE_OK; -} - -void -acpi_os_unmap_memory(void *virt, ACPI_SIZE size) -{ - iounmap(virt); -} - -acpi_status -acpi_os_get_physical_address(void *virt, ACPI_PHYSICAL_ADDRESS *phys) -{ - if(!phys || !virt) - return AE_BAD_PARAMETER; - - *phys = virt_to_phys(virt); - - return AE_OK; -} - -static void -acpi_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - (*acpi_irq_handler)(acpi_irq_context); -} - -acpi_status -acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context) -{ -#ifdef _IA64 - irq = isa_irq_to_vector(irq); -#endif /*_IA64*/ - acpi_irq_irq = irq; - acpi_irq_handler = handler; - acpi_irq_context = context; - if (request_irq(irq, acpi_irq, SA_SHIRQ, "acpi", acpi_irq)) { - printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); - return AE_NOT_ACQUIRED; - } - - return AE_OK; -} - -acpi_status -acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler) -{ - if (acpi_irq_handler) { -#ifdef _IA64 - irq = isa_irq_to_vector(irq); -#endif /*_IA64*/ - free_irq(irq, acpi_irq); - acpi_irq_handler = NULL; - } - - return AE_OK; -} - -/* - * Running in interpreter thread context, safe to sleep - */ - -void -acpi_os_sleep(u32 sec, u32 ms) -{ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ * sec + (ms * HZ) / 1000); -} - -void -acpi_os_stall(u32 us) -{ - if (us > 10000) { - mdelay(us / 1000); - } - else { - udelay(us); - } -} - -acpi_status -acpi_os_read_port( - ACPI_IO_ADDRESS port, - void *value, - u32 width) -{ - u32 dummy; - - if (!value) - value = &dummy; - - switch (width) - { - case 8: - *(u8*) value = inb(port); - break; - case 16: - *(u16*) value = inw(port); - break; - case 32: - *(u32*) value = inl(port); - break; - default: - BUG(); - } - - return AE_OK; -} - -acpi_status -acpi_os_write_port( - ACPI_IO_ADDRESS port, - acpi_integer value, - u32 width) -{ - switch (width) - { - case 8: - outb(value, port); - break; - case 16: - outw(value, port); - break; - case 32: - outl(value, port); - break; - default: - BUG(); - } - - return AE_OK; -} - -acpi_status -acpi_os_read_memory( - ACPI_PHYSICAL_ADDRESS phys_addr, - void *value, - u32 width) -{ - u32 dummy; - - if (!value) - value = &dummy; - - switch (width) - { - case 8: - *(u8*) value = *(u8*) phys_to_virt(phys_addr); - break; - case 16: - *(u16*) value = *(u16*) phys_to_virt(phys_addr); - break; - case 32: - *(u32*) value = *(u32*) phys_to_virt(phys_addr); - break; - default: - BUG(); - } - - return AE_OK; -} - -acpi_status -acpi_os_write_memory( - ACPI_PHYSICAL_ADDRESS phys_addr, - acpi_integer value, - u32 width) -{ - switch (width) - { - case 8: - *(u8*) phys_to_virt(phys_addr) = value; - break; - case 16: - *(u16*) phys_to_virt(phys_addr) = value; - break; - case 32: - *(u32*) phys_to_virt(phys_addr) = value; - break; - default: - BUG(); - } - - return AE_OK; -} - - -acpi_status -acpi_os_read_pci_configuration ( - acpi_pci_id *pci_id, - u32 reg, - void *value, - u32 width) -{ - int result = 0; - if (!value) - return AE_BAD_PARAMETER; - - switch (width) - { - case 8: - result = pci_config_read(pci_id->segment, pci_id->bus, - pci_id->device, pci_id->function, reg, 1, value); - break; - case 16: - result = pci_config_read(pci_id->segment, pci_id->bus, - pci_id->device, pci_id->function, reg, 2, value); - break; - case 32: - result = pci_config_read(pci_id->segment, pci_id->bus, - pci_id->device, pci_id->function, reg, 4, value); - break; - default: - BUG(); - } - - return (result ? AE_ERROR : AE_OK); -} - -acpi_status -acpi_os_write_pci_configuration ( - acpi_pci_id *pci_id, - u32 reg, - acpi_integer value, - u32 width) -{ - int result = 0; - - switch (width) - { - case 8: - result = pci_config_write(pci_id->segment, pci_id->bus, - pci_id->device, pci_id->function, reg, 1, value); - break; - case 16: - result = pci_config_write(pci_id->segment, pci_id->bus, - pci_id->device, pci_id->function, reg, 2, value); - break; - case 32: - result = pci_config_write(pci_id->segment, pci_id->bus, - pci_id->device, pci_id->function, reg, 4, value); - break; - default: - BUG(); - } - - return (result ? AE_ERROR : AE_OK); -} - - -acpi_status -acpi_os_load_module ( - char *module_name) -{ - ACPI_FUNCTION_TRACE ("os_load_module"); - - if (!module_name) - return_ACPI_STATUS (AE_BAD_PARAMETER); - - if (0 > request_module(module_name)) { - ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to load module [%s].\n", module_name)); - return_ACPI_STATUS (AE_ERROR); - } - - return_ACPI_STATUS (AE_OK); -} - -acpi_status -acpi_os_unload_module ( - char *module_name) -{ - if (!module_name) - return AE_BAD_PARAMETER; - - /* TODO: How on Linux? */ - /* this is done automatically for all modules with - use_count = 0, I think. see: MOD_INC_USE_COUNT -ASG */ - - return AE_OK; -} - - -/* - * See acpi_os_queue_for_execution() - */ -static int -acpi_os_queue_exec ( - void *context) -{ - ACPI_OS_DPC *dpc = (ACPI_OS_DPC*)context; - - ACPI_FUNCTION_TRACE ("os_queue_exec"); - - daemonize(); - strcpy(current->comm, "kacpidpc"); - - if (!dpc || !dpc->function) - return_ACPI_STATUS (AE_BAD_PARAMETER); - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Executing function [%p(%p)].\n", dpc->function, dpc->context)); - - dpc->function(dpc->context); - - kfree(dpc); - - return_ACPI_STATUS (AE_OK); -} - -static void -acpi_os_schedule_exec ( - void *context) -{ - ACPI_OS_DPC *dpc = NULL; - int thread_pid = -1; - - ACPI_FUNCTION_TRACE ("os_schedule_exec"); - - dpc = (ACPI_OS_DPC*)context; - if (!dpc) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n")); - return_VOID; - } - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Creating new thread to run function [%p(%p)].\n", dpc->function, dpc->context)); - - thread_pid = kernel_thread(acpi_os_queue_exec, dpc, - (CLONE_FS | CLONE_FILES | SIGCHLD)); - if (thread_pid < 0) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to kernel_thread() failed.\n")); - acpi_os_free(dpc); - } - return_VOID; -} - -acpi_status -acpi_os_queue_for_execution( - u32 priority, - OSD_EXECUTION_CALLBACK function, - void *context) -{ - acpi_status status = AE_OK; - ACPI_OS_DPC *dpc = NULL; - - ACPI_FUNCTION_TRACE ("os_queue_for_execution"); - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); - - if (!function) - return_ACPI_STATUS (AE_BAD_PARAMETER); - - /* - * Queue via DPC: - * -------------- - * Note that we have to use two different processes for queuing DPCs: - * Interrupt-Level: Use schedule_task; can't spawn a new thread. - * Kernel-Level: Spawn a new kernel thread, as schedule_task has - * its limitations (e.g. single-threaded model), and - * all other task queues run at interrupt-level. - */ - switch (priority) { - - case OSD_PRIORITY_GPE: - { - static struct tq_struct task; - - /* - * Allocate/initialize DPC structure. Note that this memory will be - * freed by the callee. - */ - dpc = kmalloc(sizeof(ACPI_OS_DPC), GFP_ATOMIC); - if (!dpc) - return_ACPI_STATUS (AE_NO_MEMORY); - - dpc->function = function; - dpc->context = context; - - memset(&task, 0, sizeof(struct tq_struct)); - - task.routine = acpi_os_schedule_exec; - task.data = (void*)dpc; - - if (schedule_task(&task) < 0) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to schedule_task() failed.\n")); - status = AE_ERROR; - } - } - break; - - default: - /* - * Allocate/initialize DPC structure. Note that this memory will be - * freed by the callee. - */ - dpc = kmalloc(sizeof(ACPI_OS_DPC), GFP_KERNEL); - if (!dpc) - return_ACPI_STATUS (AE_NO_MEMORY); - - dpc->function = function; - dpc->context = context; - - acpi_os_schedule_exec(dpc); - break; - } - - return_ACPI_STATUS (status); -} - - -acpi_status -acpi_os_create_semaphore( - u32 max_units, - u32 initial_units, - acpi_handle *handle) -{ - struct semaphore *sem = NULL; - - ACPI_FUNCTION_TRACE ("os_create_semaphore"); - - sem = acpi_os_callocate(sizeof(struct semaphore)); - if (!sem) - return_ACPI_STATUS (AE_NO_MEMORY); - - sema_init(sem, initial_units); - - *handle = (acpi_handle*)sem; - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Creating semaphore[%p|%d].\n", *handle, initial_units)); - - return_ACPI_STATUS (AE_OK); -} - - -/* - * TODO: A better way to delete semaphores? Linux doesn't have a - * 'delete_semaphore()' function -- may result in an invalid - * pointer dereference for non-synchronized consumers. Should - * we at least check for blocked threads and signal/cancel them? - */ - -acpi_status -acpi_os_delete_semaphore( - acpi_handle handle) -{ - struct semaphore *sem = (struct semaphore*) handle; - - ACPI_FUNCTION_TRACE ("os_delete_semaphore"); - - if (!sem) - return_ACPI_STATUS (AE_BAD_PARAMETER); - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Deleting semaphore[%p].\n", handle)); - - acpi_os_free(sem); sem = NULL; - - return_ACPI_STATUS (AE_OK); -} - - -/* - * TODO: The kernel doesn't have a 'down_timeout' function -- had to - * improvise. The process is to sleep for one scheduler quantum - * until the semaphore becomes available. Downside is that this - * may result in starvation for timeout-based waits when there's - * lots of semaphore activity. - * - * TODO: Support for units > 1? - */ -acpi_status -acpi_os_wait_semaphore( - acpi_handle handle, - u32 units, - u32 timeout) -{ - acpi_status status = AE_OK; - struct semaphore *sem = (struct semaphore*)handle; - int ret = 0; - - ACPI_FUNCTION_TRACE ("os_wait_semaphore"); - - if (!sem || (units < 1)) - return_ACPI_STATUS (AE_BAD_PARAMETER); - - if (units > 1) - return_ACPI_STATUS (AE_SUPPORT); - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); - - switch (timeout) - { - /* - * No Wait: - * -------- - * A zero timeout value indicates that we shouldn't wait - just - * acquire the semaphore if available otherwise return AE_TIME - * (a.k.a. 'would block'). - */ - case 0: - if(down_trylock(sem)) - status = AE_TIME; - break; - - /* - * Wait Indefinitely: - * ------------------ - */ - case WAIT_FOREVER: - ret = down_interruptible(sem); - if (ret < 0) - status = AE_ERROR; - break; - - /* - * Wait w/ Timeout: - * ---------------- - */ - default: - // TODO: A better timeout algorithm? - { - int i = 0; - static const int quantum_ms = 1000/HZ; - - ret = down_trylock(sem); - for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - ret = down_trylock(sem); - } - - if (ret != 0) - status = AE_TIME; - } - break; - } - - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Failed to acquire semaphore[%p|%d|%d]\n", handle, units, timeout)); - } - else { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout)); - } - - return_ACPI_STATUS (status); -} - - -/* - * TODO: Support for units > 1? - */ -acpi_status -acpi_os_signal_semaphore( - acpi_handle handle, - u32 units) -{ - struct semaphore *sem = (struct semaphore *) handle; - - ACPI_FUNCTION_TRACE ("os_signal_semaphore"); - - if (!sem || (units < 1)) - return_ACPI_STATUS (AE_BAD_PARAMETER); - - if (units > 1) - return_ACPI_STATUS (AE_SUPPORT); - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Signaling semaphore[%p|%d]\n", handle, units)); - - up(sem); - - return_ACPI_STATUS (AE_OK); -} - -u32 -acpi_os_get_line(NATIVE_CHAR *buffer) -{ - -#ifdef ENABLE_DEBUGGER - if (acpi_in_debugger) { - u32 chars; - - kdb_read(buffer, sizeof(line_buf)); - - /* remove the CR kdb includes */ - chars = strlen(buffer) - 1; - buffer[chars] = '\0'; - } -#endif - - return 0; -} - -/* - * We just have to assume we're dealing with valid memory - */ - -BOOLEAN -acpi_os_readable(void *ptr, u32 len) -{ - return 1; -} - -BOOLEAN -acpi_os_writable(void *ptr, u32 len) -{ - return 1; -} - -u32 -acpi_os_get_thread_id (void) -{ - if (!in_interrupt()) - return current->pid; - - return 0; -} - -acpi_status -acpi_os_signal ( - u32 function, - void *info) -{ - switch (function) - { - case ACPI_SIGNAL_FATAL: - printk(KERN_ERR PREFIX "Fatal opcode executed\n"); - break; - case ACPI_SIGNAL_BREAKPOINT: - { - char *bp_info = (char*) info; - - printk(KERN_ERR "ACPI breakpoint: %s\n", bp_info); - } - default: - break; - } - - return AE_OK; -} - -acpi_status -acpi_os_breakpoint(NATIVE_CHAR *msg) -{ - acpi_os_printf("breakpoint: %s", msg); - - return AE_OK; -} - diff -Nru a/drivers/acpi/acpi_pci_link.c b/drivers/acpi/acpi_pci_link.c --- a/drivers/acpi/acpi_pci_link.c Sun Jun 2 18:44:56 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,588 +0,0 @@ -/* - * acpi_pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 22 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * TBD: - * 1. Support more than one IRQ resource entry per link device. - * 2. Implement start/stop mechanism and use ACPI Bus Driver facilities - * for IRQ management (e.g. start()->_SRS). - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "acpi_bus.h" -#include "acpi_drivers.h" - - -#define _COMPONENT ACPI_PCI_LINK_COMPONENT -ACPI_MODULE_NAME ("acpi_pci_link") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_PCI_DRIVER_NAME); -MODULE_LICENSE("GPL"); - -#define PREFIX "ACPI: " - -#define ACPI_PCI_LINK_MAX_IRQS 16 - - -static int acpi_pci_link_add (struct acpi_device *device); -static int acpi_pci_link_remove (struct acpi_device *device, int type); - -static struct acpi_driver acpi_pci_link_driver = { - name: ACPI_PCI_LINK_DRIVER_NAME, - class: ACPI_PCI_LINK_CLASS, - ids: ACPI_PCI_LINK_HID, - ops: { - add: acpi_pci_link_add, - remove: acpi_pci_link_remove, - }, -}; - -struct acpi_pci_link_irq { - u8 active; /* Current IRQ */ - u8 possible_count; - u8 possible[ACPI_PCI_LINK_MAX_IRQS]; - struct { - u8 valid:1; - u8 enabled:1; - u8 shareable:1; /* 0 = Exclusive */ - u8 polarity:1; /* 0 = Active-High */ - u8 trigger:1; /* 0 = Level-Triggered */ - u8 producer:1; /* 0 = Consumer-Only */ - u8 reserved:2; - } flags; -}; - -struct acpi_pci_link { - acpi_handle handle; - struct acpi_pci_link_irq irq; -}; - - -/* -------------------------------------------------------------------------- - PCI Link Device Management - -------------------------------------------------------------------------- */ - -static int -acpi_pci_link_get_possible ( - struct acpi_pci_link *link) -{ - int result = 0; - acpi_status status = AE_OK; - acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_resource *resource = NULL; - int i = 0; - - ACPI_FUNCTION_TRACE("acpi_pci_link_get_possible"); - - if (!link) - return_VALUE(-EINVAL); - - status = acpi_get_possible_resources(link->handle, &buffer); - if (ACPI_FAILURE(status) || !buffer.pointer) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n")); - result = -ENODEV; - goto end; - } - - resource = (acpi_resource *) buffer.pointer; - - switch (resource->id) { - case ACPI_RSTYPE_IRQ: - { - acpi_resource_irq *p = &resource->data.irq; - - if (!p || !p->number_of_interrupts) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Blank IRQ resource\n")); - result = -ENODEV; - goto end; - } - - for (i = 0; (inumber_of_interrupts && iirq.possible[i] = p->interrupts[i]; - link->irq.possible_count++; - } - - link->irq.flags.trigger = p->edge_level; - link->irq.flags.polarity = p->active_high_low; - link->irq.flags.shareable = p->shared_exclusive; - - break; - } - case ACPI_RSTYPE_EXT_IRQ: - { - acpi_resource_ext_irq *p = &resource->data.extended_irq; - - if (!p || !p->number_of_interrupts) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Blank IRQ resource\n")); - result = -ENODEV; - goto end; - } - - for (i = 0; (inumber_of_interrupts && iirq.possible[i] = p->interrupts[i]; - link->irq.possible_count++; - } - - link->irq.flags.trigger = p->edge_level; - link->irq.flags.polarity = p->active_high_low; - link->irq.flags.shareable = p->shared_exclusive; - - break; - } - default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Resource is not an IRQ entry\n")); - result = -ENODEV; - goto end; - break; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found %d possible IRQs\n", link->irq.possible_count)); - -end: - kfree(buffer.pointer); - - return_VALUE(result); -} - - -static int -acpi_pci_link_get_current ( - struct acpi_pci_link *link) -{ - int result = 0; - acpi_status status = AE_OK; - acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_resource *resource = NULL; - - ACPI_FUNCTION_TRACE("acpi_pci_link_get_current"); - - if (!link || !link->handle) - return_VALUE(-EINVAL); - - link->irq.active = 0; - - status = acpi_get_current_resources(link->handle, &buffer); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n")); - result = -ENODEV; - goto end; - } - - resource = (acpi_resource *) buffer.pointer; - - switch (resource->id) { - case ACPI_RSTYPE_IRQ: - { - acpi_resource_irq *p = &resource->data.irq; - - if (!p || !p->number_of_interrupts) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Blank IRQ resource\n")); - result = -ENODEV; - goto end; - } - - link->irq.active = p->interrupts[0]; - - break; - } - case ACPI_RSTYPE_EXT_IRQ: - { - acpi_resource_ext_irq *p = &resource->data.extended_irq; - - if (!p || !p->number_of_interrupts) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Blank IRQ resource\n")); - result = -ENODEV; - goto end; - } - - link->irq.active = p->interrupts[0]; - - break; - } - default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Resource is not an IRQ entry\n")); - break; - } - - if (!link->irq.active) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid IRQ %d\n", link->irq.active)); - result = -ENODEV; - } - -end: - kfree(buffer.pointer); - - if (0 == result) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", - link->irq.active)); - - return_VALUE(result); -} - - -static int -acpi_pci_link_set ( - struct acpi_pci_link *link, - int irq) -{ - acpi_status status = AE_OK; - struct { - acpi_resource res; - acpi_resource end; - } resource; - acpi_buffer buffer = {sizeof(resource)+1, &resource}; - - ACPI_FUNCTION_TRACE("acpi_pci_link_set"); - - if (!link || !irq) - return_VALUE(-EINVAL); - - memset(&resource, 0, sizeof(resource)); - - resource.res.id = ACPI_RSTYPE_IRQ; - resource.res.length = sizeof(acpi_resource); - resource.res.data.irq.edge_level = link->irq.flags.trigger; - resource.res.data.irq.active_high_low = link->irq.flags.polarity; - resource.res.data.irq.shared_exclusive = link->irq.flags.shareable; - resource.res.data.irq.number_of_interrupts = 1; - resource.res.data.irq.interrupts[0] = irq; - resource.end.id = ACPI_RSTYPE_END_TAG; - - status = acpi_set_current_resources(link->handle, &buffer); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n")); - return_VALUE(-ENODEV); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", irq)); - - return_VALUE(0); -} - - -int -acpi_pci_link_get_irq ( - struct acpi_prt_entry *entry, - int *irq) -{ - int result = -ENODEV; - struct acpi_device *device = NULL; - struct acpi_pci_link *link = NULL; - - ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq"); - - if (!entry || !entry->source.handle || !irq) - return_VALUE(-EINVAL); - - /* TBD: Support multiple index values (not just first). */ - if (0 != entry->source.index) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unsupported resource index [%d]\n", - entry->source.index)); - return_VALUE(-ENODEV); - } - - result = acpi_bus_get_device(entry->source.handle, &device); - if (0 != result) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link IRQ invalid\n")); - return_VALUE(-ENODEV); - } - - link = (struct acpi_pci_link *) acpi_driver_data(device); - if (!link) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); - return_VALUE(-ENODEV); - } - - if (!link->irq.flags.valid) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link IRQ invalid\n")); - return_VALUE(-ENODEV); - } - - /* TBD: Support multiple index (IRQ) entries per Link Device */ - if (0 != entry->source.index) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unsupported IRQ resource index [%d]\n", - entry->source.index)); - return_VALUE(-EFAULT); - } - - *irq = link->irq.active; - - return_VALUE(0); -} - - -int -acpi_pci_link_set_irq ( - struct acpi_prt_entry *entry, - int irq) -{ - int result = 0; - int i = 0; - int valid = 0; - struct acpi_device *device = NULL; - struct acpi_pci_link *link = NULL; - - ACPI_FUNCTION_TRACE("acpi_pci_link_set_irq"); - - if (!entry || !entry->source.handle || !irq) - return_VALUE(-EINVAL); - - /* TBD: Support multiple index (IRQ) entries per Link Device */ - if (0 != entry->source.index) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unsupported resource index [%d]\n", - entry->source.index)); - return_VALUE(-ENODEV); - } - - result = acpi_bus_get_device(entry->source.handle, &device); - if (0 != result) - return_VALUE(result); - - link = (struct acpi_pci_link *) acpi_driver_data(device); - if (!link) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); - return_VALUE(-ENODEV); - } - - if (!link->irq.flags.valid) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link IRQ invalid\n")); - return_VALUE(-ENODEV); - } - - /* Is the target IRQ the same as the currently enabled IRQ? */ - if (link->irq.flags.enabled && (irq == link->irq.active)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link already at IRQ %d\n", - irq)); - return_VALUE(0); - } - - /* Is the target IRQ in the list of possible IRQs? */ - for (i=0; iirq.possible_count; i++) { - if (irq == link->irq.possible[i]) - valid = 1; - } - if (!valid) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Target IRQ invalid\n")); - return_VALUE(-EINVAL); - } - - /* TBD: Do we need to disable this link device before resetting? */ - - /* Set the new IRQ */ - result = acpi_pci_link_set(link, irq); - if (0 != result) - return_VALUE(result); - - link->irq.active = irq; - - return_VALUE(result); -} - - -static int -acpi_pci_link_enable ( - struct acpi_device *device, - struct acpi_pci_link *link) -{ - int result = -ENODEV; - - ACPI_FUNCTION_TRACE("acpi_pci_link_enable"); - - if (!device || !link) - return_VALUE(-EINVAL); - - result = acpi_pci_link_get_possible(link); - if (0 != result) - return_VALUE(result); - - result = acpi_bus_get_status(device); - if (0 != result) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n")); - return_VALUE(-ENODEV); - } - - /* - * If this link device isn't enabled (_STA bit 1) then we enable it - * by setting an IRQ. - */ - if (!device->status.enabled) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Attempting to enable at IRQ [%d]\n", - link->irq.possible[0])); - - result = acpi_pci_link_set(link, link->irq.possible[0]); - if (0 != result) - return_VALUE(result); - - result = acpi_bus_get_status(device); - if (0 != result) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to read status\n")); - return_VALUE(-ENODEV); - } - - if (!device->status.enabled) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Enable failed\n")); - return_VALUE(-ENODEV); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link enabled at IRQ %d\n", - link->irq.possible[0])); - } - - /* - * Now we get the current IRQ just to make sure everything is kosher. - */ - result = acpi_pci_link_get_current(link); - if (0 != result) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Current IRQ invalid, setting to default\n")); - - result = acpi_pci_link_set(link, link->irq.possible[0]); - if (0 != result) - return_VALUE(result); - - result = acpi_pci_link_get_current(link); - if (0 != result) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to read current IRQ\n")); - return_VALUE(result); - } - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Using IRQ %d\n", link->irq.active)); - - link->irq.flags.valid = 1; - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ - -static int -acpi_pci_link_add ( - struct acpi_device *device) -{ - int result = 0; - struct acpi_pci_link *link = NULL; - int i = 0; - - ACPI_FUNCTION_TRACE("acpi_pci_link_add"); - - if (!device) - return_VALUE(-EINVAL); - - link = kmalloc(sizeof(struct acpi_pci_link), GFP_KERNEL); - if (!link) - return_VALUE(-ENOMEM); - memset(link, 0, sizeof(struct acpi_pci_link)); - - link->handle = device->handle; - sprintf(acpi_device_name(device), "%s", ACPI_PCI_LINK_DEVICE_NAME); - sprintf(acpi_device_class(device), "%s", ACPI_PCI_LINK_CLASS); - acpi_driver_data(device) = link; - - result = acpi_pci_link_enable(device, link); - if (0 != result) - goto end; - - printk(PREFIX "%s [%s] (IRQs", - acpi_device_name(device), acpi_device_bid(device)); - for (i = 0; i < link->irq.possible_count; i++) - printk("%s%d", - (link->irq.active==link->irq.possible[i])?" *":" ", - link->irq.possible[i]); - printk(")\n"); - -end: - if (0 != result) - kfree(link); - - return_VALUE(result); -} - - -static int -acpi_pci_link_remove ( - struct acpi_device *device, - int type) -{ - struct acpi_pci_link *link = NULL; - - ACPI_FUNCTION_TRACE("acpi_pci_link_remove"); - - if (!device || !acpi_driver_data(device)) - return_VALUE(-EINVAL); - - link = (struct acpi_pci_link *) acpi_driver_data(device); - - kfree(link); - - return_VALUE(0); -} - - -int __init -acpi_pci_link_init (void) -{ - ACPI_FUNCTION_TRACE("acpi_pci_link_init"); - - if (0 > acpi_bus_register_driver(&acpi_pci_link_driver)) - return_VALUE(-ENODEV); - - return_VALUE(0); -} - - -void __exit -acpi_pci_link_exit (void) -{ - ACPI_FUNCTION_TRACE("acpi_pci_link_init"); - - acpi_bus_unregister_driver(&acpi_pci_link_driver); - - return_VOID; -} diff -Nru a/drivers/acpi/acpi_pci_root.c b/drivers/acpi/acpi_pci_root.c --- a/drivers/acpi/acpi_pci_root.c Sun Jun 2 18:44:56 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,747 +0,0 @@ -/* - * acpi_pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 30 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "acpi_bus.h" -#include "acpi_drivers.h" - - -#define _COMPONENT ACPI_PCI_ROOT_COMPONENT -ACPI_MODULE_NAME ("pci_root") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_PCI_ROOT_DRIVER_NAME); - -extern struct pci_ops *pci_root_ops; - -#define PREFIX "ACPI: " - -static int acpi_pci_root_add (struct acpi_device *device); -static int acpi_pci_root_remove (struct acpi_device *device, int type); -static int acpi_pci_root_bind (struct acpi_device *device); - -static struct acpi_driver acpi_pci_root_driver = { - name: ACPI_PCI_ROOT_DRIVER_NAME, - class: ACPI_PCI_ROOT_CLASS, - ids: ACPI_PCI_ROOT_HID, - ops: { - add: acpi_pci_root_add, - remove: acpi_pci_root_remove, - bind: acpi_pci_root_bind, - }, -}; - -struct acpi_pci_data { - acpi_pci_id id; - struct pci_dev *dev; -}; - -struct acpi_pci_root { - acpi_handle handle; - struct acpi_pci_data data; -}; - -struct acpi_prt_list acpi_prts; - - -/* -------------------------------------------------------------------------- - PCI Routing Table (PRT) Support - -------------------------------------------------------------------------- */ - -static int -acpi_prt_find_entry ( - acpi_pci_id *id, - u8 pin, - struct acpi_prt_entry **entry) -{ - struct list_head *node = NULL; - - ACPI_FUNCTION_TRACE("acpi_prt_find_entry"); - - if (!id || !entry) - return_VALUE(-ENODEV); - - /* TBD: Locking */ - list_for_each(node, &acpi_prts.entries) { - (*entry) = list_entry(node, struct acpi_prt_entry, node); - /* TBD: Include check for segment when supported by pci_dev */ - if ((id->bus == (*entry)->id.bus) - && (id->device == (*entry)->id.dev) - && (pin == (*entry)->id.pin)) { - return_VALUE(0); - } - } - - (*entry) = NULL; - - return_VALUE(-ENODEV); -} - - -int -acpi_prt_get_irq ( - struct pci_dev *dev, - u8 pin, - int *irq) -{ - int result = 0; - struct acpi_prt_entry *entry = NULL; - acpi_pci_id id = {0, 0, 0, 0}; - - ACPI_FUNCTION_TRACE("acpi_prt_get_irq"); - - if (!dev || !irq) - return_VALUE(-ENODEV); - - if (!dev->bus) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Device has invalid 'bus' field\n")); - return_VALUE(-EFAULT); - } - - id.segment = 0; - id.bus = dev->bus->number; - id.device = PCI_SLOT(dev->devfn); - id.function = PCI_FUNC(dev->devfn); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Resolving IRQ for %02x:%02x:%02x.%02x[%c]\n", - id.segment, id.bus, id.device, id.function, ('A'+pin))); - - result = acpi_prt_find_entry(&id, pin, &entry); - if (0 != result) - return_VALUE(result); - - /* Type 1: Dynamic (e.g. PCI Link Device) */ - if (entry->source.handle) - result = acpi_pci_link_get_irq(entry, irq); - - /* Type 2: Static (e.g. I/O [S]APIC Direct) */ - else { - if (entry->source.index) - *irq = entry->source.index; - else - result = -ENODEV; - } - - if (0 == result) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", *irq)); - else - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to reslove IRQ\n")); - - return_VALUE(0); -} - - -int -acpi_prt_set_irq ( - struct pci_dev *dev, - u8 pin, - int irq) -{ - int result = 0; - struct acpi_prt_entry *entry = NULL; - acpi_pci_id id = {0, 0, 0, 0}; - - ACPI_FUNCTION_TRACE("acpi_pci_set_irq"); - - if (!dev || !irq) - return_VALUE(-EINVAL); - - if (!dev->bus) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Device has invalid 'bus' field\n")); - return_VALUE(-EFAULT); - } - - id.segment = 0; - id.bus = dev->bus->number; - id.device = PCI_SLOT(dev->devfn); - id.function = PCI_FUNC(dev->devfn); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Setting %02x:%02x:%02x.%02x[%c] to IRQ%d\n", - id.segment, id.bus, id.device, id.function, ('A'+pin), irq)); - - result = acpi_prt_find_entry(&id, pin, &entry); - if (0 != result) - return_VALUE(result); - - /* Type 1: Dynamic (e.g. PCI Link Device) */ - if (entry->source.handle) - result = acpi_pci_link_set_irq(entry, irq); - /* Type 2: Static (e.g. I/O [S]APIC Direct) */ - else - result = -EFAULT; - - if (0 == result) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "IRQ set\n")); - else - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to set IRQ\n")); - - return_VALUE(result); -} - - -static int -acpi_prt_add_entry ( - acpi_handle handle, - u8 seg, - u8 bus, - acpi_pci_routing_table *prt) -{ - struct acpi_prt_entry *entry = NULL; - - ACPI_FUNCTION_TRACE("acpi_prt_add_entry"); - - if (!prt) - return_VALUE(-EINVAL); - - entry = kmalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL); - if (!entry) - return_VALUE(-ENOMEM); - memset(entry, 0, sizeof(struct acpi_prt_entry)); - - entry->id.seg = seg; - entry->id.bus = bus; - entry->id.dev = prt->address >> 16; - entry->id.pin = prt->pin; - - /* - * Type 1: Dynamic - * --------------- - * The 'source' field specifies the PCI interrupt link device used to - * configure the IRQ assigned to this slot|dev|pin. The 'source_index' - * indicates which resource descriptor in the resource template (of - * the link device) this interrupt is allocated from. - */ - if (prt->source) - acpi_get_handle(handle, prt->source, &entry->source.handle); - /* - * Type 2: Static - * -------------- - * The 'source' field is NULL, and the 'source_index' field specifies - * the IRQ value, which is hardwired to specific interrupt inputs on - * the interrupt controller. - */ - else - entry->source.handle = NULL; - - entry->source.index = prt->source_index; - - /* - * NOTE: Don't query the Link Device for IRQ information at this time - * because Link Device enumeration may not have occurred yet - * (e.g. exists somewhere 'below' this _PRT entry in the ACPI - * namespace). - */ - - ACPI_DEBUG_PRINT_RAW((ACPI_DB_OK, " %02X:%02X:%02X[%c] -> %s[%d]\n", - entry->id.seg, entry->id.bus, entry->id.dev, - ('A' + entry->id.pin), prt->source, entry->source.index)); - - /* TBD: Acquire/release lock */ - list_add_tail(&entry->node, &acpi_prts.entries); - - acpi_prts.count++; - - return_VALUE(0); -} - - -static int -acpi_prt_parse ( - acpi_handle handle, - u8 seg, - u8 bus) -{ - acpi_status status = AE_OK; - char pathname[PATHNAME_MAX] = {0}; - acpi_buffer buffer = {0, NULL}; - acpi_pci_routing_table *prt = NULL; - - ACPI_FUNCTION_TRACE("acpi_prt_parse"); - - buffer.length = sizeof(pathname); - buffer.pointer = pathname; - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); - - printk(KERN_INFO PREFIX "%s [%s._PRT]\n", ACPI_PCI_PRT_DEVICE_NAME, - pathname); - - /* - * Evaluate this _PRT and add all entries to our global list. - */ - - buffer.length = 0; - buffer.pointer = NULL; - status = acpi_get_irq_routing_table(handle, &buffer); - if (status != AE_BUFFER_OVERFLOW) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error evaluating _PRT [%s]\n", - acpi_format_exception(status))); - return_VALUE(-ENODEV); - } - - prt = kmalloc(buffer.length, GFP_KERNEL); - if (!prt) - return_VALUE(-ENOMEM); - memset(prt, 0, buffer.length); - buffer.pointer = prt; - - status = acpi_get_irq_routing_table(handle, &buffer); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error evaluating _PRT [%s]\n", - acpi_format_exception(status))); - kfree(buffer.pointer); - return_VALUE(-ENODEV); - } - - while (prt && (prt->length > 0)) { - acpi_prt_add_entry(handle, seg, bus, prt); - prt = (acpi_pci_routing_table*)((unsigned long)prt + prt->length); - } - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - PCI Device Binding - -------------------------------------------------------------------------- */ - -static void -acpi_pci_data_handler ( - acpi_handle handle, - u32 function, - void *context) -{ - ACPI_FUNCTION_TRACE("acpi_pci_data_handler"); - - /* TBD: Anything we need to do here? */ - - return_VOID; -} - - -/** - * acpi_os_get_pci_id - * ------------------ - * This function gets used by the ACPI Interpreter (a.k.a. Core Subsystem) - * to resolve PCI information for ACPI-PCI devices defined in the namespace. - */ -acpi_status -acpi_os_get_pci_id ( - acpi_handle handle, - acpi_pci_id *id) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_device *device = NULL; - struct acpi_pci_data *data = NULL; - - ACPI_FUNCTION_TRACE("acpi_os_get_pci_id"); - - if (!id) - return_ACPI_STATUS(AE_BAD_PARAMETER); - - result = acpi_bus_get_device(handle, &device); - if (0 != result) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid ACPI Bus context for device %s\n", - acpi_device_bid(device))); - return_ACPI_STATUS(AE_NOT_EXIST); - } - - status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data); - if (ACPI_FAILURE(status) || !data || !data->dev) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid ACPI-PCI context for device %s\n", - acpi_device_bid(device))); - return_ACPI_STATUS(status); - } - - id->segment = data->id.segment; - id->bus = data->id.bus; - id->device = data->id.device; - id->function = data->id.function; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device %s has PCI address %02x:%02x:%02x.%02x\n", - acpi_device_bid(device), id->segment, id->bus, - id->device, id->function)); - - return_ACPI_STATUS(AE_OK); -} - - -static int -acpi_pci_root_bind ( - struct acpi_device *device) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_pci_data *data = NULL; - struct acpi_pci_data *parent_data = NULL; - acpi_handle handle = NULL; - - ACPI_FUNCTION_TRACE("acpi_pci_root_bind"); - - if (!device || !device->parent) - return_VALUE(-EINVAL); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Attempting to bind PCI device %s.%s\n", - acpi_device_bid(device->parent), acpi_device_bid(device))); - - data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); - if (!data) - return_VALUE(-ENOMEM); - memset(data, 0, sizeof(struct acpi_pci_data)); - - /* - * Segment & Bus - * ------------- - * These are obtained via the parent device's ACPI-PCI context.. - * Note that PCI root bridge devices don't have a 'dev->subordinate'. - */ - status = acpi_get_data(device->parent->handle, acpi_pci_data_handler, - (void**) &parent_data); - if (ACPI_FAILURE(status) || !parent_data || !parent_data->dev) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid ACPI-PCI context for parent device %s\n", - acpi_device_bid(device->parent))); - result = -ENODEV; - goto end; - } - - data->id.segment = parent_data->id.segment; - - if (parent_data->dev->subordinate) /* e.g. PCI-PCI bridge */ - data->id.bus = parent_data->dev->subordinate->number; - else if (parent_data->dev->bus) /* PCI root bridge */ - data->id.bus = parent_data->dev->bus->number; - else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Parent device %s is not a PCI bridge\n", - acpi_device_bid(device->parent))); - result = -ENODEV; - goto end; - } - - /* - * Device & Function - * ----------------- - * These are simply obtained from the device's _ADR method. Note - * that a value of zero is valid. - */ - data->id.device = device->pnp.bus_address >> 16; - data->id.function = device->pnp.bus_address & 0xFFFF; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Binding device %s.%s to %02x:%02x:%02x.%02x\n", - acpi_device_bid(device->parent), acpi_device_bid(device), - data->id.segment, data->id.bus, data->id.device, - data->id.function)); - - /* - * Locate PCI Device - * ----------------- - * Locate matching device in PCI namespace. If it doesn't exist - * this typically means that the device isn't currently inserted - * (e.g. docking station, port replicator, etc.). - */ - data->dev = pci_find_slot(data->id.bus, - PCI_DEVFN(data->id.device, data->id.function)); - if (!data->dev) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Device %02x:%02x:%02x.%02x not present in PCI namespace\n", - data->id.segment, data->id.bus, - data->id.device, data->id.function)); - result = -ENODEV; - goto end; - } - if (!data->dev->bus) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Device %02x:%02x:%02x.%02x has invalid 'bus' field\n", - data->id.segment, data->id.bus, - data->id.device, data->id.function)); - result = -ENODEV; - goto end; - } - - /* - * Attach ACPI-PCI Context - * ----------------------- - * Thus binding the ACPI and PCI devices. - */ - status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to attach ACPI-PCI context to device %s\n", - acpi_device_bid(device))); - result = -ENODEV; - goto end; - } - - /* - * PCI Bridge? - * ----------- - * If so, install the 'bind' function to facilitate callbacks for - * all of its children. - */ - if (data->dev->subordinate) - device->ops.bind = acpi_pci_root_bind; - - /* - * PCI Routing Table - * ----------------- - * Evaluate and parse _PRT, if exists. This code is independent of - * PCI bridges (above) to allow parsing of _PRT objects within the - * scope of non-bridge devices. Note that _PRTs within the scope of - * a PCI bridge assume the bridge's subordinate bus number. - * - * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? - */ - status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); - if (ACPI_SUCCESS(status)) { - if (data->dev->subordinate) /* PCI-PCI bridge */ - acpi_prt_parse(device->handle, data->id.segment, - data->dev->subordinate->number); - else /* non-bridge PCI device */ - acpi_prt_parse(device->handle, data->id.segment, - data->id.bus); - } - -end: - if (0 != result) - kfree(data); - - return_VALUE(result); -} - - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ - -static int -acpi_pci_root_add ( - struct acpi_device *device) -{ - int result = 0; - struct acpi_pci_root *root = NULL; - acpi_status status = AE_OK; - unsigned long value = 0; - - ACPI_FUNCTION_TRACE("acpi_pci_root_add"); - - if (!device) - return_VALUE(-EINVAL); - - root = kmalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); - if (!root) - return_VALUE(-ENOMEM); - memset(root, 0, sizeof(struct acpi_pci_root)); - - root->handle = device->handle; - sprintf(acpi_device_name(device), "%s", ACPI_PCI_ROOT_DEVICE_NAME); - sprintf(acpi_device_class(device), "%s", ACPI_PCI_ROOT_CLASS); - acpi_driver_data(device) = root; - - /* - * TBD: Doesn't the bus driver automatically set this? - */ - device->ops.bind = acpi_pci_root_bind; - - /* - * Segment - * ------- - * Obtained via _SEG, if exists, otherwise assumed to be zero (0). - */ - status = acpi_evaluate_integer(root->handle, METHOD_NAME__SEG, NULL, - &value); - switch (status) { - case AE_OK: - root->data.id.segment = (u16) value; - break; - case AE_NOT_FOUND: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming segment 0 (no _SEG)\n")); - root->data.id.segment = 0; - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SEG\n")); - result = -ENODEV; - goto end; - } - - /* - * Bus - * --- - * Obtained via _BBN, if exists, otherwise assumed to be zero (0). - */ - status = acpi_evaluate_integer(root->handle, METHOD_NAME__BBN, NULL, - &value); - switch (status) { - case AE_OK: - root->data.id.bus = (u16) value; - break; - case AE_NOT_FOUND: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming bus 0 (no _BBN)\n")); - root->data.id.bus = 0; - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BBN\n")); - result = -ENODEV; - goto end; - } - - /* - * Device & Function - * ----------------- - * Obtained from _ADR (which has already been evaluated for us). - */ - root->data.id.device = device->pnp.bus_address >> 16; - root->data.id.function = device->pnp.bus_address & 0xFFFF; - - /* - * TBD: Evaluate _CRS to get root bridge resources - * TBD: Need PCI interface for enumeration/configuration of roots. - */ - - printk(KERN_INFO PREFIX "%s [%s] (%02x:%02x:%02x.%02x)\n", - acpi_device_name(device), acpi_device_bid(device), - root->data.id.segment, root->data.id.bus, - root->data.id.device, root->data.id.function); - - /* - * Scan the Root Bridge - * -------------------- - * Must do this prior to any attempt to bind the root device, as the - * PCI namespace does not get created until this call is made (and - * thus the root bridge's pci_dev does not exist). - */ - pci_scan_bus(root->data.id.bus, pci_root_ops, NULL); - - /* - * Locate PCI Device - * ----------------- - * Locate the matching PCI root bridge device in the PCI namespace. - */ - root->data.dev = pci_find_slot(root->data.id.bus, - PCI_DEVFN(root->data.id.device, root->data.id.function)); - if (!root->data.dev) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Device %02x:%02x:%02x.%02x not present\n", - root->data.id.segment, root->data.id.bus, - root->data.id.device, root->data.id.function)); - result = -ENODEV; - goto end; - } - - /* - * Attach ACPI-PCI Context - * ----------------------- - * Thus binding the ACPI and PCI devices. - */ - status = acpi_attach_data(root->handle, acpi_pci_data_handler, - &root->data); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to attach ACPI-PCI context to device %s\n", - acpi_device_bid(device))); - result = -ENODEV; - goto end; - } - - /* - * PCI Routing Table - * ----------------- - * Evaluate and parse _PRT, if exists. Note that root bridges - * must have a _PRT (optional for subordinate bridges). - */ - result = acpi_prt_parse(device->handle, root->data.id.segment, - root->data.id.bus); - -end: - if (0 != result) - kfree(root); - - return_VALUE(result); -} - - -static int -acpi_pci_root_remove ( - struct acpi_device *device, - int type) -{ - struct acpi_pci_root *root = NULL; - - ACPI_FUNCTION_TRACE("acpi_pci_root_remove"); - - if (!device || !acpi_driver_data(device)) - return_VALUE(-EINVAL); - - root = (struct acpi_pci_root *) acpi_driver_data(device); - - kfree(root); - - return_VALUE(0); -} - - -int __init -acpi_pci_root_init (void) -{ - ACPI_FUNCTION_TRACE("acpi_pci_root_init"); - - acpi_prts.count = 0; - INIT_LIST_HEAD(&acpi_prts.entries); - - if (0 > acpi_bus_register_driver(&acpi_pci_root_driver)) - return_VALUE(-ENODEV); - - return_VALUE(0); -} - - -void __exit -acpi_pci_root_exit (void) -{ - ACPI_FUNCTION_TRACE("acpi_pci_root_exit"); - - acpi_bus_unregister_driver(&acpi_pci_root_driver); - - return_VOID; -} diff -Nru a/drivers/acpi/acpi_power.c b/drivers/acpi/acpi_power.c --- a/drivers/acpi/acpi_power.c Sun Jun 2 18:44:56 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,610 +0,0 @@ -/* - * acpi_power.c - ACPI Bus Power Management ($Revision: 34 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include "acpi_bus.h" -#include "acpi_drivers.h" - - -#define _COMPONENT ACPI_POWER_COMPONENT -ACPI_MODULE_NAME ("acpi_power") - -#define PREFIX "ACPI: " - - -int acpi_power_add (struct acpi_device *device); -int acpi_power_remove (struct acpi_device *device, int type); - -static struct acpi_driver acpi_power_driver = { - name: ACPI_POWER_DRIVER_NAME, - class: ACPI_POWER_CLASS, - ids: ACPI_POWER_HID, - ops: { - add: acpi_power_add, - remove: acpi_power_remove, - }, -}; - -struct acpi_power_resource -{ - acpi_handle handle; - acpi_bus_id name; - u32 system_level; - u32 order; - int state; - int references; -}; - -static struct list_head acpi_power_resource_list; - - -/* -------------------------------------------------------------------------- - Power Resource Management - -------------------------------------------------------------------------- */ - -static int -acpi_power_get_context ( - acpi_handle handle, - struct acpi_power_resource **resource) -{ - int result = 0; - struct acpi_device *device = NULL; - - ACPI_FUNCTION_TRACE("acpi_power_get_context"); - - if (!resource) - return_VALUE(-ENODEV); - - result = acpi_bus_get_device(handle, &device); - if (0 != result) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error getting context [%p]\n", - handle)); - return_VALUE(result); - } - - *resource = (struct acpi_power_resource *) acpi_driver_data(device); - if (!resource) - return_VALUE(-ENODEV); - - return_VALUE(0); -} - - -static int -acpi_power_get_state ( - struct acpi_power_resource *resource) -{ - acpi_status status = AE_OK; - unsigned long sta = 0; - - ACPI_FUNCTION_TRACE("acpi_power_get_state"); - - if (!resource) - return_VALUE(-EINVAL); - - status = acpi_evaluate_integer(resource->handle, "_STA", NULL, &sta); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - if (sta & 0x01) - resource->state = ACPI_POWER_RESOURCE_STATE_ON; - else - resource->state = ACPI_POWER_RESOURCE_STATE_OFF; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", - resource->name, resource->state?"on":"off")); - - return_VALUE(0); -} - - -static int -acpi_power_get_list_state ( - struct acpi_handle_list *list, - int *state) -{ - int result = 0; - struct acpi_power_resource *resource = NULL; - u32 i = 0; - - ACPI_FUNCTION_TRACE("acpi_power_get_list_state"); - - if (!list || !state) - return_VALUE(-EINVAL); - - /* The state of the list is 'on' IFF all resources are 'on'. */ - - for (i=0; icount; i++) { - result = acpi_power_get_context(list->handles[i], &resource); - if (0 != result) - return_VALUE(result); - result = acpi_power_get_state(resource); - if (0 != result) - return_VALUE(result); - - *state = resource->state; - - if (*state != ACPI_POWER_RESOURCE_STATE_ON) - break; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n", - *state?"on":"off")); - - return_VALUE(result); -} - - -static int -acpi_power_on ( - acpi_handle handle) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_device *device = NULL; - struct acpi_power_resource *resource = NULL; - - ACPI_FUNCTION_TRACE("acpi_power_on"); - - result = acpi_power_get_context(handle, &resource); - if (0 != result) - return_VALUE(result); - - resource->references++; - - if ((resource->references > 1) - || (resource->state == ACPI_POWER_RESOURCE_STATE_ON)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n", - resource->name)); - return_VALUE(0); - } - - status = acpi_evaluate(resource->handle, "_ON", NULL, NULL); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - result = acpi_power_get_state(resource); - if (0 != result) - return_VALUE(result); - if (resource->state != ACPI_POWER_RESOURCE_STATE_ON) - return_VALUE(-ENOEXEC); - - /* Update the power resource's _device_ power state */ - result = acpi_bus_get_device(resource->handle, &device); - if (0 != result) - return_VALUE(result); - device->power.state = ACPI_STATE_D0; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n", - resource->name)); - - return_VALUE(0); -} - - -static int -acpi_power_off ( - acpi_handle handle) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_device *device = NULL; - struct acpi_power_resource *resource = NULL; - - ACPI_FUNCTION_TRACE("acpi_power_off"); - - result = acpi_power_get_context(handle, &resource); - if (0 != result) - return_VALUE(result); - - if (resource->references) - resource->references--; - - if (resource->references) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Resource [%s] is still in use, dereferencing\n", - device->pnp.bus_id)); - return_VALUE(0); - } - - if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n", - device->pnp.bus_id)); - return_VALUE(0); - } - - status = acpi_evaluate(resource->handle, "_OFF", NULL, NULL); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - result = acpi_power_get_state(resource); - if (0 != result) - return_VALUE(result); - if (resource->state != ACPI_POWER_RESOURCE_STATE_OFF) - return_VALUE(-ENOEXEC); - - /* Update the power resource's _device_ power state */ - result = acpi_bus_get_device(resource->handle, &device); - if (0 != result) - return_VALUE(result); - device->power.state = ACPI_STATE_D3; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n", - resource->name)); - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Device Power Management - -------------------------------------------------------------------------- */ - -int -acpi_power_get_inferred_state ( - struct acpi_device *device) -{ - int result = 0; - struct acpi_handle_list *list = NULL; - int list_state = 0; - int i = 0; - - ACPI_FUNCTION_TRACE("acpi_power_get_inferred_state"); - - if (!device) - return_VALUE(-EINVAL); - - device->power.state = ACPI_STATE_UNKNOWN; - - /* - * We know a device's inferred power state when all the resources - * required for a given D-state are 'on'. - */ - for (i=ACPI_STATE_D0; ipower.states[i].resources; - if (list->count < 1) - continue; - - result = acpi_power_get_list_state(list, &list_state); - if (0 != result) - return_VALUE(result); - - if (list_state == ACPI_POWER_RESOURCE_STATE_ON) { - device->power.state = i; - return_VALUE(0); - } - } - - device->power.state = ACPI_STATE_D3; - - return_VALUE(0); -} - - -int -acpi_power_transition ( - struct acpi_device *device, - int state) -{ - int result = 0; - struct acpi_handle_list *cl = NULL; /* Current Resources */ - struct acpi_handle_list *tl = NULL; /* Target Resources */ - int i = 0; - - ACPI_FUNCTION_TRACE("acpi_power_transition"); - - if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) - return_VALUE(-EINVAL); - - cl = &device->power.states[device->power.state].resources; - tl = &device->power.states[state].resources; - - device->power.state = ACPI_STATE_UNKNOWN; - - if (!cl->count && !tl->count) { - result = -ENODEV; - goto end; - } - - /* TBD: Resources must be ordered. */ - - /* - * First we reference all power resources required in the target list - * (e.g. so the device doesn't loose power while transitioning). - */ - for (i=0; icount; i++) { - result = acpi_power_on(tl->handles[i]); - if (0 != result) - goto end; - } - - device->power.state = state; - - /* - * Then we dereference all power resources used in the current list. - */ - for (i=0; icount; i++) { - result = acpi_power_off(cl->handles[i]); - if (0 != result) - goto end; - } - -end: - if (0 != result) - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Error transitioning device [%s] to D%d\n", - device->pnp.bus_id, state)); - - return_VALUE(result); -} - - -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -#include -#include - -struct proc_dir_entry *acpi_power_dir = NULL; - - -static int -acpi_power_read_status ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_power_resource *resource = NULL; - char *p = page; - int len; - - ACPI_FUNCTION_TRACE("acpi_power_read_status"); - - if (!data || (off != 0)) - goto end; - - resource = (struct acpi_power_resource *) data; - - p += sprintf(p, "state: "); - switch (resource->state) { - case ACPI_POWER_RESOURCE_STATE_ON: - p += sprintf(p, "on\n"); - break; - case ACPI_POWER_RESOURCE_STATE_OFF: - p += sprintf(p, "off\n"); - break; - default: - p += sprintf(p, "unknown\n"); - break; - } - - p += sprintf(p, "system level: S%d\n", - resource->system_level); - p += sprintf(p, "order: %d\n", - resource->order); - p += sprintf(p, "reference count: %d\n", - resource->references); - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_power_add_fs ( - struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - - ACPI_FUNCTION_TRACE("acpi_power_add_fs"); - - if (!device) - return_VALUE(-EINVAL); - - if (!acpi_power_dir) { - acpi_power_dir = proc_mkdir(ACPI_POWER_CLASS, acpi_root_dir); - if (!acpi_power_dir) - return_VALUE(-ENODEV); - } - - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_power_dir); - if (!acpi_device_dir(device)) - return_VALUE(-ENODEV); - } - - /* 'status' [R] */ - entry = create_proc_entry(ACPI_POWER_FILE_STATUS, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_POWER_FILE_STATUS)); - else { - entry->read_proc = acpi_power_read_status; - entry->data = acpi_driver_data(device); - } - - return_VALUE(0); -} - - -static int -acpi_power_remove_fs ( - struct acpi_device *device) -{ - ACPI_FUNCTION_TRACE("acpi_power_remove_fs"); - - if (!acpi_power_dir) - return_VALUE(-ENODEV); - - if (acpi_device_dir(device)) - remove_proc_entry(acpi_device_bid(device), acpi_power_dir); - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ - -int -acpi_power_add ( - struct acpi_device *device) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_power_resource *resource = NULL; - acpi_object acpi_object; - acpi_buffer buffer = {sizeof(acpi_object), &acpi_object}; - - ACPI_FUNCTION_TRACE("acpi_power_add"); - - if (!device) - return_VALUE(-EINVAL); - - resource = kmalloc(sizeof(struct acpi_power_resource), GFP_KERNEL); - if (!resource) - return_VALUE(-ENOMEM); - memset(resource, 0, sizeof(struct acpi_power_resource)); - - resource->handle = device->handle; - sprintf(resource->name, "%s", device->pnp.bus_id); - sprintf(acpi_device_name(device), "%s", ACPI_POWER_DEVICE_NAME); - sprintf(acpi_device_class(device), "%s", ACPI_POWER_CLASS); - acpi_driver_data(device) = resource; - - /* Evalute the object to get the system level and resource order. */ - status = acpi_evaluate_object(resource->handle, NULL, NULL, &buffer); - if (ACPI_FAILURE(status)) { - result = -ENODEV; - goto end; - } - resource->system_level = acpi_object.power_resource.system_level; - resource->order = acpi_object.power_resource.resource_order; - - result = acpi_power_get_state(resource); - if (0 != result) - goto end; - - switch (resource->state) { - case ACPI_POWER_RESOURCE_STATE_ON: - device->power.state = ACPI_STATE_D0; - break; - case ACPI_POWER_RESOURCE_STATE_OFF: - device->power.state = ACPI_STATE_D3; - break; - default: - device->power.state = ACPI_STATE_UNKNOWN; - break; - } - - result = acpi_power_add_fs(device); - if (0 != result) - goto end; - - printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), - acpi_device_bid(device), resource->state?"on":"off"); - -end: - if (0 != result) - kfree(resource); - - return_VALUE(result); -} - - -int -acpi_power_remove ( - struct acpi_device *device, - int type) -{ - struct acpi_power_resource *resource = NULL; - - ACPI_FUNCTION_TRACE("acpi_power_remove"); - - if (!device || !acpi_driver_data(device)) - return_VALUE(-EINVAL); - - resource = (struct acpi_power_resource *) acpi_driver_data(device); - - acpi_power_remove_fs(device); - - kfree(resource); - - return_VALUE(0); -} - - -int __init -acpi_power_init (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_power_init"); - - INIT_LIST_HEAD(&acpi_power_resource_list); - - result = acpi_bus_register_driver(&acpi_power_driver); - if (0 > result) { - remove_proc_entry(ACPI_POWER_CLASS, acpi_root_dir); - return_VALUE(-ENODEV); - } - - return_VALUE(0); -} - - -void __exit -acpi_power_exit (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_power_exit"); - - /* TBD: Empty acpi_power_resource_list */ - - result = acpi_bus_unregister_driver(&acpi_power_driver); - if (0 == result) - remove_proc_entry(ACPI_POWER_CLASS, acpi_root_dir); - - return_VOID; -} diff -Nru a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c --- a/drivers/acpi/acpi_processor.c Sun Jun 2 18:44:58 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,2292 +0,0 @@ -/* - * acpi_processor.c - ACPI Processor Driver ($Revision: 57 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * TBD: - * 1. Make # power/performance states dynamic. - * 2. Support duty_cycle values that span bit 4. - * 3. Optimize by having scheduler determine business instead of - * having us try to calculate it here. - * 4. Need C1 timing -- must modify kernel (IRQ handler) to get this. - * 5. Convert time values to ticks (initially) to avoid having to do - * the math (acpi_get_timer_duration). - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "acpi_bus.h" -#include "acpi_drivers.h" - - -#define _COMPONENT ACPI_PROCESSOR_COMPONENT -ACPI_MODULE_NAME ("acpi_processor") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME); -MODULE_LICENSE("GPL"); - -#define PREFIX "ACPI: " - -#define ACPI_PROCESSOR_BUSY_METRIC 10 - -#define ACPI_PROCESSOR_MAX_POWER ACPI_C_STATE_COUNT -#define ACPI_PROCESSOR_MAX_C2_LATENCY 100 -#define ACPI_PROCESSOR_MAX_C3_LATENCY 1000 - -#define ACPI_PROCESSOR_MAX_PERFORMANCE 8 - -#define ACPI_PROCESSOR_MAX_THROTTLING 16 -#define ACPI_PROCESSOR_MAX_THROTTLE 250 /* 25% */ -#define ACPI_PROCESSOR_MAX_DUTY_WIDTH 4 - -const u32 POWER_OF_2[] = {1,2,4,8,16,32,64}; - -#define ACPI_PROCESSOR_LIMIT_USER 0 -#define ACPI_PROCESSOR_LIMIT_THERMAL 1 - -static int acpi_processor_add (struct acpi_device *device); -static int acpi_processor_remove (struct acpi_device *device, int type); - -static struct acpi_driver acpi_processor_driver = { - name: ACPI_PROCESSOR_DRIVER_NAME, - class: ACPI_PROCESSOR_CLASS, - ids: ACPI_PROCESSOR_HID, - ops: { - add: acpi_processor_add, - remove: acpi_processor_remove, - }, -}; - -/* Power Management */ - -struct acpi_processor_cx_policy { - u32 count; - int state; - struct { - u32 time; - u32 count; - u32 bm; - } threshold; -}; - -struct acpi_processor_cx { - u8 valid; - u32 address; - u32 latency; - u32 power; - u32 usage; - struct acpi_processor_cx_policy promotion; - struct acpi_processor_cx_policy demotion; -}; - -struct acpi_processor_power { - int state; - int default_state; - u32 bm_activity; - struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER]; -}; - -/* Performance Management */ - -struct acpi_pct_register { - u8 descriptor; - u16 length; - u8 space_id; - u8 bit_width; - u8 bit_offset; - u8 reserved; - u64 address; -} __attribute__ ((packed)); - -struct acpi_processor_px { - acpi_integer core_frequency; /* megahertz */ - acpi_integer power; /* milliWatts */ - acpi_integer transition_latency; /* microseconds */ - acpi_integer bus_master_latency; /* microseconds */ - acpi_integer control; /* control value */ - acpi_integer status; /* success indicator */ -}; - -struct acpi_processor_performance { - int state; - int platform_limit; - u16 control_register; - u16 status_register; - int state_count; - struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE]; -}; - - -/* Throttling Control */ - -struct acpi_processor_tx { - u16 power; - u16 performance; -}; - -struct acpi_processor_throttling { - int state; - u32 address; - u8 duty_offset; - u8 duty_width; - int state_count; - struct acpi_processor_tx states[ACPI_PROCESSOR_MAX_THROTTLING]; -}; - -/* Limit Interface */ - -struct acpi_processor_lx { - int px; /* performace state */ - int tx; /* throttle level */ -}; - -struct acpi_processor_limit { - struct acpi_processor_lx state; /* current limit */ - struct acpi_processor_lx thermal; /* thermal limit */ - struct acpi_processor_lx user; /* user limit */ -}; - - -struct acpi_processor_flags { - u8 power:1; - u8 performance:1; - u8 throttling:1; - u8 limit:1; - u8 bm_control:1; - u8 bm_check:1; - u8 reserved:2; -}; - -struct acpi_processor { - acpi_handle handle; - u32 acpi_id; - u32 id; - struct acpi_processor_flags flags; - struct acpi_processor_power power; - struct acpi_processor_performance performance; - struct acpi_processor_throttling throttling; - struct acpi_processor_limit limit; -}; - -struct acpi_processor_errata { - u8 smp; - struct { - u8 throttle:1; - u8 fdma:1; - u8 reserved:6; - u32 bmisx; - } piix4; -}; - -static struct acpi_processor *processors[NR_CPUS]; -static struct acpi_processor_errata errata; -static void (*pm_idle_save)(void) = NULL; - - -/* -------------------------------------------------------------------------- - Errata Handling - -------------------------------------------------------------------------- */ - -int -acpi_processor_errata_piix4 ( - struct pci_dev *dev) -{ - u8 rev = 0; - u8 value1 = 0; - u8 value2 = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_errata_piix4"); - - if (!dev) - return_VALUE(-EINVAL); - - /* - * Note that 'dev' references the PIIX4 ACPI Controller. - */ - - pci_read_config_byte(dev, PCI_REVISION_ID, &rev); - - switch (rev) { - case 0: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n")); - break; - case 1: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n")); - break; - case 2: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n")); - break; - case 3: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n")); - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n")); - break; - } - - switch (rev) { - - case 0: /* PIIX4 A-step */ - case 1: /* PIIX4 B-step */ - /* - * See specification changes #13 ("Manual Throttle Duty Cycle") - * and #14 ("Enabling and Disabling Manual Throttle"), plus - * erratum #5 ("STPCLK# Deassertion Time") from the January - * 2002 PIIX4 specification update. Applies to only older - * PIIX4 models. - */ - errata.piix4.throttle = 1; - - case 2: /* PIIX4E */ - case 3: /* PIIX4M */ - /* - * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA - * Livelock") from the January 2002 PIIX4 specification update. - * Applies to all PIIX4 models. - */ - - /* - * BM-IDE - * ------ - * Find the PIIX4 IDE Controller and get the Bus Master IDE - * Status register address. We'll use this later to read - * each IDE controller's DMA status to make sure we catch all - * DMA activity. - */ - dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB, - PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev) - errata.piix4.bmisx = pci_resource_start(dev, 4); - - /* - * Type-F DMA - * ---------- - * Find the PIIX4 ISA Controller and read the Motherboard - * DMA controller's status to see if Type-F (Fast) DMA mode - * is enabled (bit 7) on either channel. Note that we'll - * disable C3 support if this is enabled, as some legacy - * devices won't operate well if fast DMA is disabled. - */ - dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_0, - PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev) { - pci_read_config_byte(dev, 0x76, &value1); - pci_read_config_byte(dev, 0x77, &value2); - if ((value1 & 0x80) || (value2 & 0x80)) - errata.piix4.fdma = 1; - } - - break; - } - - if (errata.piix4.bmisx) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Bus master activity detection (BM-IDE) erratum enabled\n")); - if (errata.piix4.fdma) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Type-F DMA livelock erratum (C3 disabled)\n")); - - return_VALUE(0); -} - - -int -acpi_processor_errata ( - struct acpi_processor *pr) -{ - int result = 0; - struct pci_dev *dev = NULL; - - ACPI_FUNCTION_TRACE("acpi_processor_errata"); - - if (!pr) - return_VALUE(-EINVAL); - - /* - * PIIX4 - */ - dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev) - result = acpi_processor_errata_piix4(dev); - - return_VALUE(result); -} - - -/* -------------------------------------------------------------------------- - Power Management - -------------------------------------------------------------------------- */ - -static void -acpi_processor_power_activate ( - struct acpi_processor *pr, - int state) -{ - if (!pr) - return; - - pr->power.states[pr->power.state].promotion.count = 0; - pr->power.states[pr->power.state].demotion.count = 0; - - /* Cleanup from old state. */ - switch (pr->power.state) { - case ACPI_STATE_C3: - /* Disable bus master reload */ - acpi_hw_bit_register_write(ACPI_BITREG_BUS_MASTER_RLD, 0, ACPI_MTX_DO_NOT_LOCK); - break; - } - - /* Prepare to use new state. */ - switch (state) { - case ACPI_STATE_C3: - /* Enable bus master reload */ - acpi_hw_bit_register_write(ACPI_BITREG_BUS_MASTER_RLD, 1, ACPI_MTX_DO_NOT_LOCK); - break; - } - - pr->power.state = state; - - return; -} - - -static void -acpi_processor_idle (void) -{ - struct acpi_processor *pr = NULL; - struct acpi_processor_cx *cx = NULL; - int next_state = 0; - u32 start_ticks = 0; - u32 end_ticks = 0; - u32 time_elapsed = 0; - - pr = processors[smp_processor_id()]; - if (!pr) - return; - - /* - * Interrupts must be disabled during bus mastering calculations and - * for C2/C3 transitions. - */ - __cli(); - - cx = &(pr->power.states[pr->power.state]); - - /* - * Check BM Activity - * ----------------- - * Check for bus mastering activity (if required), record, and check - * for demotion. - */ - if (pr->flags.bm_check) { - - pr->power.bm_activity <<= 1; - pr->power.bm_activity &= 0xFFFFFFFE; - - if (acpi_hw_bit_register_read(ACPI_BITREG_BUS_MASTER_STATUS, ACPI_MTX_DO_NOT_LOCK)) { - pr->power.bm_activity++; - acpi_hw_bit_register_write(ACPI_BITREG_BUS_MASTER_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); - } - /* - * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect - * the true state of bus mastering activity; forcing us to - * manually check the BMIDEA bit of each IDE channel. - */ - else if (errata.piix4.bmisx) { - if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01) - || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01)) - pr->power.bm_activity++; - } - - /* - * Apply bus mastering demotion policy. Automatically demote - * to avoid a faulty transition. Note that the processor - * won't enter a low-power state during this call (to this - * funciton) but should upon the next. - */ - if (pr->power.bm_activity & cx->demotion.threshold.bm) { - __sti(); - next_state = cx->demotion.state; - goto end; - } - } - - cx->usage++; - - /* - * Sleep: - * ------ - * Invoke the current Cx state to put the processor to sleep. - */ - switch (pr->power.state) { - - case ACPI_STATE_C1: - /* Invoke C1. */ - safe_halt(); - /* - * TBD: Can't get time duration while in C1, as resumes - * go to an ISR rather than here. Need to instrument - * base interrupt handler. - */ - time_elapsed = 0xFFFFFFFF; - break; - - case ACPI_STATE_C2: - /* See how long we're asleep for */ - start_ticks = inl(acpi_fadt.Xpm_tmr_blk.address); - /* Invoke C2 */ - inb(pr->power.states[ACPI_STATE_C2].address); - /* Dummy op - must do something useless after P_LVL2 read */ - end_ticks = inl(acpi_fadt.Xpm_tmr_blk.address); - /* Compute time elapsed */ - end_ticks = inl(acpi_fadt.Xpm_tmr_blk.address); - /* Re-enable interrupts */ - __sti(); - /* - * Compute the amount of time asleep (in the Cx state). - * TBD: Convert to PM timer ticks initially to avoid having - * to do the math (acpi_get_timer_duration). - */ - acpi_get_timer_duration(start_ticks, end_ticks, &time_elapsed); - break; - - case ACPI_STATE_C3: - /* Disable bus master arbitration */ - acpi_hw_bit_register_write(ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK); - /* See how long we're asleep for */ - start_ticks = inl(acpi_fadt.Xpm_tmr_blk.address); - /* Invoke C3 */ - inb(pr->power.states[ACPI_STATE_C3].address); - /* Dummy op - must do something useless after P_LVL3 read */ - end_ticks = inl(acpi_fadt.Xpm_tmr_blk.address); - /* Compute time elapsed */ - end_ticks = inl(acpi_fadt.Xpm_tmr_blk.address); - /* Enable bus master arbitration */ - acpi_hw_bit_register_write(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK); - /* Re-enable interrupts */ - __sti(); - /* - * Compute the amount of time asleep (in the Cx state). - * TBD: Convert to PM timer ticks initially to avoid having - * to do the math (acpi_get_timer_duration). - */ - acpi_get_timer_duration(start_ticks, end_ticks, &time_elapsed); - break; - - default: - __sti(); - return; - } - - next_state = pr->power.state; - - /* - * Promotion? - * ---------- - * Track the number of longs (time asleep is greater than threshold) - * and promote when the count threshold is reached. Note that bus - * mastering activity may prevent promotions. - */ - if (cx->promotion.state) { - if (time_elapsed >= cx->promotion.threshold.time) { - cx->promotion.count++; - cx->demotion.count = 0; - if (cx->promotion.count >= cx->promotion.threshold.count) { - if (pr->flags.bm_check) { - if (!(pr->power.bm_activity & cx->promotion.threshold.bm)) { - next_state = cx->promotion.state; - goto end; - } - } - else { - next_state = cx->promotion.state; - goto end; - } - } - } - } - - /* - * Demotion? - * --------- - * Track the number of shorts (time asleep is less than time threshold) - * and demote when the usage threshold is reached. Note that bus - * mastering demotions are checked prior to state transitions (above). - */ - if (cx->demotion.state) { - if (time_elapsed < cx->demotion.threshold.time) { - cx->demotion.count++; - cx->promotion.count = 0; - if (cx->demotion.count >= cx->demotion.threshold.count) { - next_state = cx->demotion.state; - goto end; - } - } - } - -end: - /* - * New Cx State? - * ------------- - * If we're going to start using a new Cx state we must clean up - * from the previous and prepare to use the new. - */ - if (next_state != pr->power.state) - acpi_processor_power_activate(pr, next_state); - - return; -} - - -static int -acpi_processor_set_power_policy ( - struct acpi_processor *pr) -{ - ACPI_FUNCTION_TRACE("acpi_processor_set_power_policy"); - - /* - * This function sets the default Cx state policy (OS idle handler). - * Our scheme is to promote quickly to C2 but more conservatively - * to C3. We're favoring C2 for its characteristics of low latency - * (quick response), good power savings, and ability to allow bus - * mastering activity. Note that the Cx state policy is completely - * customizable and can be altered dynamically. - */ - - if (!pr) - return_VALUE(-EINVAL); - - /* - * C0/C1 - * ----- - */ - pr->power.state = ACPI_STATE_C1; - pr->power.default_state = ACPI_STATE_C1; - - /* - * C1/C2 - * ----- - * Set the default C1 promotion and C2 demotion policies, where we - * promote from C1 to C2 after several (10) successive C1 transitions, - * as we cannot (currently) measure the time spent in C1. Demote from - * C2 to C1 after experiencing several (3) 'shorts' (time spent in C2 - * is less than the C2 transtional latency). - */ - if (pr->power.states[ACPI_STATE_C2].valid) { - pr->power.states[ACPI_STATE_C1].promotion.threshold.count = 10; - pr->power.states[ACPI_STATE_C1].promotion.threshold.time = - pr->power.states[ACPI_STATE_C2].latency; - pr->power.states[ACPI_STATE_C1].promotion.state = ACPI_STATE_C2; - - pr->power.states[ACPI_STATE_C2].demotion.threshold.count = 3; - pr->power.states[ACPI_STATE_C2].demotion.threshold.time = - pr->power.states[ACPI_STATE_C2].latency; - pr->power.states[ACPI_STATE_C2].demotion.state = ACPI_STATE_C1; - } - - /* - * C2/C3 - * ----- - * Set default C2 promotion and C3 demotion policies, where we promote - * from C2 to C3 after 4 cycles (0x0F) of no bus mastering activity - * (while maintaining sleep time criteria). Demote immediately on a - * short or whenever bus mastering activity occurs. - */ - if ((pr->power.states[ACPI_STATE_C2].valid) && - (pr->power.states[ACPI_STATE_C3].valid)) { - pr->power.states[ACPI_STATE_C2].promotion.threshold.count = 1; - pr->power.states[ACPI_STATE_C2].promotion.threshold.time = - pr->power.states[ACPI_STATE_C3].latency; - pr->power.states[ACPI_STATE_C2].promotion.threshold.bm = 0x0F; - pr->power.states[ACPI_STATE_C2].promotion.state = ACPI_STATE_C3; - - pr->power.states[ACPI_STATE_C3].demotion.threshold.count = 1; - pr->power.states[ACPI_STATE_C3].demotion.threshold.time = - pr->power.states[ACPI_STATE_C3].latency; - pr->power.states[ACPI_STATE_C3].demotion.threshold.bm = 0x0F; - pr->power.states[ACPI_STATE_C3].demotion.state = ACPI_STATE_C2; - } - - return_VALUE(0); -} - - -int -acpi_processor_get_power_info ( - struct acpi_processor *pr) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_get_power_info"); - - if (!pr) - return_VALUE(-EINVAL); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "lvl2[0x%08x] lvl3[0x%08x]\n", - pr->power.states[ACPI_STATE_C2].address, - pr->power.states[ACPI_STATE_C3].address)); - - /* TBD: Support ACPI 2.0 objects */ - - /* - * C0 - * -- - * This state exists only as filler in our array. - */ - pr->power.states[ACPI_STATE_C0].valid = 1; - - /* - * C1 - * -- - * ACPI requires C1 support for all processors. - * - * TBD: What about PROC_C1? - */ - pr->power.states[ACPI_STATE_C1].valid = 1; - - /* - * C2 - * -- - * We're (currently) only supporting C2 on UP systems. - * - * TBD: Support for C2 on MP (P_LVL2_UP). - */ - if (pr->power.states[ACPI_STATE_C2].address) { - - pr->power.states[ACPI_STATE_C2].latency = acpi_fadt.plvl2_lat; - - /* - * C2 latency must be less than or equal to 100 microseconds. - */ - if (acpi_fadt.plvl2_lat >= ACPI_PROCESSOR_MAX_C2_LATENCY) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "C2 latency too large [%d]\n", - acpi_fadt.plvl2_lat)); - /* - * Only support C2 on UP systems (see TBD above). - */ - else if (errata.smp) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "C2 not supported in SMP mode\n")); - /* - * Otherwise we've met all of our C2 requirements. - */ - else - pr->power.states[ACPI_STATE_C2].valid = 1; - } - - /* - * C3 - * -- - * TBD: Investigate use of WBINVD on UP/SMP system in absence of - * bm_control. - */ - if (pr->power.states[ACPI_STATE_C3].address) { - - pr->power.states[ACPI_STATE_C3].latency = acpi_fadt.plvl3_lat; - - /* - * C3 latency must be less than or equal to 1000 microseconds. - */ - if (acpi_fadt.plvl3_lat >= ACPI_PROCESSOR_MAX_C3_LATENCY) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "C3 latency too large [%d]\n", - acpi_fadt.plvl3_lat)); - /* - * Only support C3 when bus mastering arbitration control - * is present (able to disable bus mastering to maintain - * cache coherency while in C3). - */ - else if (!pr->flags.bm_control) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "C3 support requires bus mastering control\n")); - /* - * Only support C3 on UP systems, as bm_control is only viable - * on a UP system and flushing caches (e.g. WBINVD) is simply - * too costly (at this time). - */ - else if (errata.smp) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "C3 not supported in SMP mode\n")); - /* - * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) - * DMA transfers are used by any ISA device to avoid livelock. - * Note that we could disable Type-F DMA (as recommended by - * the erratum), but this is known to disrupt certain ISA - * devices thus we take the conservative approach. - */ - else if (errata.piix4.fdma) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "C3 not supported on PIIX4 with Type-F DMA\n")); - } - /* - * Otherwise we've met all of our C3 requirements. Enable - * checking of bus mastering status (bm_check) so we can - * use this in our C3 policy. - */ - else { - pr->power.states[ACPI_STATE_C3].valid = 1; - pr->flags.bm_check = 1; - } - } - - /* - * Set Default Policy - * ------------------ - * Now that we know which state are supported, set the default - * policy. Note that this policy can be changed dynamically - * (e.g. encourage deeper sleeps to conserve battery life when - * not on AC). - */ - result = acpi_processor_set_power_policy(pr); - if (0 != result) - return_VALUE(result); - - /* - * If this processor supports C2 or C3 we denote it as being 'power - * manageable'. Note that there's really no policy involved for - * when only C1 is supported. - */ - if (pr->power.states[ACPI_STATE_C2].valid - || pr->power.states[ACPI_STATE_C3].valid) - pr->flags.power = 1; - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Performance Management - -------------------------------------------------------------------------- */ - -static int -acpi_processor_get_platform_limit ( - struct acpi_processor* pr) -{ - acpi_status status = 0; - unsigned long ppc = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_get_platform_limit"); - - if (!pr) - return_VALUE(-EINVAL); - - /* - * _PPC indicates the maximum state currently supported by the platform - * (e.g. 0 = states 0..n; 1 = states 1..n; etc. - */ - status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc); - if(ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PPC\n")); - return_VALUE(-ENODEV); - } - - pr->performance.platform_limit = (int) ppc; - - return_VALUE(0); -} - - -static int -acpi_processor_get_performance_control ( - struct acpi_processor *pr) -{ - int result = 0; - acpi_status status = 0; - acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_object *pct = NULL; - acpi_object obj = {0}; - struct acpi_pct_register *reg = NULL; - - ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control"); - - status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer); - if(ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PCT\n")); - return_VALUE(-ENODEV); - } - - pct = (acpi_object *) buffer.pointer; - if (!pct || (pct->type != ACPI_TYPE_PACKAGE) - || (pct->package.count != 2)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PCT data\n")); - result = -EFAULT; - goto end; - } - - /* - * control_register - */ - - obj = pct->package.elements[0]; - - if ((obj.type != ACPI_TYPE_BUFFER) - || (obj.buffer.length < sizeof(struct acpi_pct_register)) - || (obj.buffer.pointer == NULL)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid _PCT data (control_register)\n")); - result = -EFAULT; - goto end; - } - - reg = (struct acpi_pct_register *) (obj.buffer.pointer); - - if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unsupported address space [%d] (control_register)\n", - (u32) reg->space_id)); - result = -EFAULT; - goto end; - } - - pr->performance.control_register = (u16) reg->address; - - /* - * status_register - */ - - obj = pct->package.elements[1]; - - if ((obj.type != ACPI_TYPE_BUFFER) - || (obj.buffer.length < sizeof(struct acpi_pct_register)) - || (obj.buffer.pointer == NULL)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid _PCT data (status_register)\n")); - result = -EFAULT; - goto end; - } - - reg = (struct acpi_pct_register *) (obj.buffer.pointer); - - if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unsupported address space [%d] (status_register)\n", - (u32) reg->space_id)); - result = -EFAULT; - goto end; - } - - pr->performance.status_register = (u16) reg->address; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "control_register[0x%04x] status_register[0x%04x]\n", - pr->performance.control_register, - pr->performance.status_register)); - -end: - kfree(buffer.pointer); - - return_VALUE(result); -} - - -static int -acpi_processor_get_performance_states ( - struct acpi_processor* pr) -{ - int result = 0; - acpi_status status = AE_OK; - acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_buffer format = {sizeof("NNNNNN"), "NNNNNN"}; - acpi_buffer state = {0, NULL}; - acpi_object *pss = NULL; - int i = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states"); - - status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer); - if(ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PSS\n")); - return_VALUE(-ENODEV); - } - - pss = (acpi_object *) buffer.pointer; - if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n")); - result = -EFAULT; - goto end; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n", - pss->package.count)); - - if (pss->package.count > ACPI_PROCESSOR_MAX_PERFORMANCE) { - pr->performance.state_count = ACPI_PROCESSOR_MAX_PERFORMANCE; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Limiting number of states to max (%d)\n", - ACPI_PROCESSOR_MAX_PERFORMANCE)); - } - else - pr->performance.state_count = pss->package.count; - - if (pr->performance.state_count > 1) - pr->flags.performance = 1; - - for (i = 0; i < pr->performance.state_count; i++) { - - struct acpi_processor_px *px = &(pr->performance.states[i]); - - state.length = sizeof(struct acpi_processor_px); - state.pointer = px; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i)); - - status = acpi_extract_package(&(pss->package.elements[i]), - &format, &state); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n")); - result = -EFAULT; - goto end; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n", - i, - (u32) px->core_frequency, - (u32) px->power, - (u32) px->transition_latency, - (u32) px->bus_master_latency, - (u32) px->control, - (u32) px->status)); - } - -end: - kfree(buffer.pointer); - - return_VALUE(result); -} - - -static int -acpi_processor_set_performance ( - struct acpi_processor *pr, - int state) -{ - u16 port = 0; - u8 value = 0; - int i = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_set_performance"); - - if (!pr) - return_VALUE(-EINVAL); - - if (!pr->flags.performance) - return_VALUE(-ENODEV); - - if (state >= pr->performance.state_count) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Invalid target state (P%d)\n", state)); - return_VALUE(-ENODEV); - } - - if (state < pr->performance.platform_limit) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Platform limit (P%d) overrides target state (P%d)\n", - pr->performance.platform_limit, state)); - return_VALUE(-ENODEV); - } - - if (state == pr->performance.state) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Already at target state (P%d)\n", state)); - return_VALUE(0); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Transitioning from P%d to P%d\n", - pr->performance.state, state)); - - /* - * First we write the target state's 'control' value to the - * control_register. - */ - - port = pr->performance.control_register; - value = (u16) pr->performance.states[state].control; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Writing 0x%02x to port 0x%04x\n", value, port)); - - outb(value, port); - - /* - * Then we read the 'status_register' and compare the value with the - * target state's 'status' to make sure the transition was successful. - * Note that we'll poll for up to 1ms (100 cycles of 10us) before - * giving up. - */ - - port = pr->performance.status_register; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Looking for 0x%02x from port 0x%04x\n", - (u8) pr->performance.states[state].status, port)); - - for (i=0; i<100; i++) { - value = inb(port); - if (value == (u8) pr->performance.states[state].status) - break; - udelay(10); - } - - if (value != pr->performance.states[state].status) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n")); - return_VALUE(-ENODEV); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Transition successful after %d microseconds\n", - i * 10)); - - pr->performance.state = state; - - return_VALUE(0); -} - - -static int -acpi_processor_get_performance_info ( - struct acpi_processor *pr) -{ - int result = 0; - acpi_status status = AE_OK; - acpi_handle handle = NULL; - - ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info"); - - if (!pr) - return_VALUE(-EINVAL); - - status = acpi_get_handle(pr->handle, "_PCT", &handle); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "ACPI-based processor performance control unavailable\n")); - return_VALUE(0); - } - - result = acpi_processor_get_performance_control(pr); - if (0 != result) - return_VALUE(result); - - result = acpi_processor_get_performance_states(pr); - if (0 != result) - return_VALUE(result); - - result = acpi_processor_get_platform_limit(pr); - if (0 != result) - return_VALUE(result); - - /* - * TBD: Don't trust the latency values we get from BIOS, but rather - * measure the latencies during run-time (e.g. get_latencies). - */ - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Throttling Control - -------------------------------------------------------------------------- */ - -static int -acpi_processor_get_throttling ( - struct acpi_processor *pr) -{ - int state = 0; - u32 value = 0; - u32 duty_mask = 0; - u32 duty_value = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_get_throttling"); - - if (!pr) - return_VALUE(-EINVAL); - - if (!pr->flags.throttling) - return_VALUE(-ENODEV); - - pr->throttling.state = 0; - - __cli(); - - duty_mask = pr->throttling.state_count - 1; - - duty_mask <<= pr->throttling.duty_offset; - - value = inl(pr->throttling.address); - - /* - * Compute the current throttling state when throttling is enabled - * (bit 4 is on). - */ - if (value & 0x10) { - duty_value = value & duty_mask; - duty_value >>= pr->throttling.duty_offset; - - if (duty_value) - state = pr->throttling.state_count-duty_value; - } - - pr->throttling.state = state; - - __sti(); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Throttling state is T%d (%d%% throttling applied)\n", - state, pr->throttling.states[state].performance)); - - return_VALUE(0); -} - - -static int -acpi_processor_set_throttling ( - struct acpi_processor *pr, - int state) -{ - u32 value = 0; - u32 duty_mask = 0; - u32 duty_value = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_set_throttling"); - - if (!pr) - return_VALUE(-EINVAL); - - if ((state < 0) || (state > (pr->throttling.state_count - 1))) - return_VALUE(-EINVAL); - - if (!pr->flags.throttling) - return_VALUE(-ENODEV); - - if (state == pr->throttling.state) - return_VALUE(0); - - __cli(); - - /* - * Calculate the duty_value and duty_mask. - */ - if (state) { - duty_value = pr->throttling.state_count - state; - - duty_value <<= pr->throttling.duty_offset; - - /* Used to clear all duty_value bits */ - duty_mask = pr->throttling.state_count - 1; - - duty_mask <<= acpi_fadt.duty_offset; - duty_mask = ~duty_mask; - } - - /* - * Disable throttling by writing a 0 to bit 4. Note that we must - * turn it off before you can change the duty_value. - */ - value = inl(pr->throttling.address); - if (value & 0x10) { - value &= 0xFFFFFFEF; - outl(value, pr->throttling.address); - } - - /* - * Write the new duty_value and then enable throttling. Note - * that a state value of 0 leaves throttling disabled. - */ - if (state) { - value &= duty_mask; - value |= duty_value; - outl(value, pr->throttling.address); - - value |= 0x00000010; - outl(value, pr->throttling.address); - } - - pr->throttling.state = state; - - __sti(); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Throttling state set to T%d (%d%%)\n", state, - (pr->throttling.states[state].performance?pr->throttling.states[state].performance/10:0))); - - return_VALUE(0); -} - - -static int -acpi_processor_get_throttling_info ( - struct acpi_processor *pr) -{ - int result = 0; - int step = 0; - int i = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_get_throttling_info"); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", - pr->throttling.address, - pr->throttling.duty_offset, - pr->throttling.duty_width)); - - if (!pr) - return_VALUE(-EINVAL); - - /* TBD: Support ACPI 2.0 objects */ - - if (!pr->throttling.address) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); - return_VALUE(0); - } - else if (!pr->throttling.duty_width) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n")); - return_VALUE(0); - } - /* TBD: Support duty_cycle values that span bit 4. */ - else if ((pr->throttling.duty_offset - + pr->throttling.duty_width) > 4) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "duty_cycle spans bit 4\n")); - return_VALUE(0); - } - - /* - * PIIX4 Errata: We don't support throttling on the original PIIX4. - * This shouldn't be an issue as few (if any) mobile systems ever - * used this part. - */ - if (errata.piix4.throttle) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Throttling not supported on PIIX4 A- or B-step\n")); - return_VALUE(0); - } - - pr->throttling.state_count = POWER_OF_2[acpi_fadt.duty_width]; - - /* - * Compute state values. Note that throttling displays a linear power/ - * performance relationship (at 50% performance the CPU will consume - * 50% power). Values are in 1/10th of a percent to preserve accuracy. - */ - - step = (1000 / pr->throttling.state_count); - - for (i=0; ithrottling.state_count; i++) { - pr->throttling.states[i].performance = step * i; - pr->throttling.states[i].power = step * i; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n", - pr->throttling.state_count)); - - pr->flags.throttling = 1; - - /* - * Disable throttling (if enabled). We'll let subsequent policy (e.g. - * thermal) decide to lower performance if it so chooses, but for now - * we'll crank up the speed. - */ - - result = acpi_processor_get_throttling(pr); - if (0 != result) - goto end; - - if (pr->throttling.state) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabling throttling (was T%d)\n", - pr->throttling.state)); - result = acpi_processor_set_throttling(pr, 0); - if (0 != result) - goto end; - } - -end: - if (0 != result) - pr->flags.throttling = 0; - - return_VALUE(result); -} - - -/* -------------------------------------------------------------------------- - Limit Interface - -------------------------------------------------------------------------- */ - -static int -acpi_processor_apply_limit ( - struct acpi_processor* pr) -{ - int result = 0; - u16 px = 0; - u16 tx = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_apply_limit"); - - if (!pr) - return_VALUE(-EINVAL); - - if (!pr->flags.limit) - return_VALUE(-ENODEV); - - if (pr->flags.performance) { - px = pr->performance.platform_limit; - if (pr->limit.user.px > px) - px = pr->limit.user.px; - if (pr->limit.thermal.px > px) - px = pr->limit.thermal.px; - - result = acpi_processor_set_performance(pr, px); - if (0 != result) - goto end; - } - - if (pr->flags.throttling) { - if (pr->limit.user.tx > tx) - tx = pr->limit.user.tx; - if (pr->limit.thermal.tx > tx) - tx = pr->limit.thermal.tx; - - result = acpi_processor_set_throttling(pr, tx); - if (0 != result) - goto end; - } - - pr->limit.state.px = px; - pr->limit.state.tx = tx; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d] limit set to (P%d:T%d)\n", - pr->id, - pr->limit.state.px, - pr->limit.state.tx)); - -end: - if (0 != result) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to set limit\n")); - - return_VALUE(result); -} - - -int -acpi_processor_set_thermal_limit ( - acpi_handle handle, - int type) -{ - int result = 0; - struct acpi_processor *pr = NULL; - struct acpi_device *device = NULL; - int px = 0; - int tx = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit"); - - if ((type < ACPI_PROCESSOR_LIMIT_NONE) - || (type > ACPI_PROCESSOR_LIMIT_DECREMENT)) - return_VALUE(-EINVAL); - - result = acpi_bus_get_device(handle, &device); - if (0 != result) - return_VALUE(result); - - pr = (struct acpi_processor *) acpi_driver_data(device); - if (!pr) - return_VALUE(-ENODEV); - - if (!pr->flags.limit) - return_VALUE(-ENODEV); - - /* Thermal limits are always relative to the current Px/Tx state. */ - if (pr->flags.performance) - pr->limit.thermal.px = pr->performance.state; - if (pr->flags.throttling) - pr->limit.thermal.tx = pr->throttling.state; - - /* - * Our default policy is to only use throttling at the lowest - * performance state. - */ - - switch (type) { - - case ACPI_PROCESSOR_LIMIT_NONE: - px = 0; - tx = 0; - break; - - case ACPI_PROCESSOR_LIMIT_INCREMENT: - if (pr->flags.performance) { - if (px == (pr->performance.state_count - 1)) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "At maximum performance state\n")); - else { - px++; - goto end; - } - } - if (pr->flags.throttling) { - if (tx == (pr->throttling.state_count - 1)) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "At maximum throttling state\n")); - else - tx++; - } - break; - - case ACPI_PROCESSOR_LIMIT_DECREMENT: - if (pr->flags.performance) { - if (px == pr->performance.platform_limit) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "At minimum performance state\n")); - else { - px--; - goto end; - } - } - if (pr->flags.throttling) { - if (tx == 0) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "At minimum throttling state\n")); - else - tx--; - } - break; - } - -end: - pr->limit.thermal.px = px; - pr->limit.thermal.tx = tx; - - result = acpi_processor_apply_limit(pr); - if (0 != result) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to set thermal limit\n")); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n", - pr->limit.thermal.px, - pr->limit.thermal.tx)); - - return_VALUE(result); -} - - -static int -acpi_processor_get_limit_info ( - struct acpi_processor *pr) -{ - ACPI_FUNCTION_TRACE("acpi_processor_get_limit_info"); - - if (!pr) - return_VALUE(-EINVAL); - - if (pr->flags.performance || pr->flags.throttling) - pr->flags.limit = 1; - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -#include -#include - -struct proc_dir_entry *acpi_processor_dir = NULL; - -static int -acpi_processor_read_info ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_processor *pr = (struct acpi_processor *) data; - char *p = page; - int len = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_read_info"); - - if (!pr || (off != 0)) - goto end; - - p += sprintf(p, "processor id: %d\n", - pr->id); - - p += sprintf(p, "acpi id: %d\n", - pr->acpi_id); - - p += sprintf(p, "bus mastering control: %s\n", - pr->flags.bm_control ? "yes" : "no"); - - p += sprintf(p, "power management: %s\n", - pr->flags.power ? "yes" : "no"); - - p += sprintf(p, "throttling control: %s\n", - pr->flags.throttling ? "yes" : "no"); - - p += sprintf(p, "performance management: %s\n", - pr->flags.performance ? "yes" : "no"); - - p += sprintf(p, "limit interface: %s\n", - pr->flags.limit ? "yes" : "no"); - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_processor_read_power ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_processor *pr = (struct acpi_processor *) data; - char *p = page; - int len = 0; - int i = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_read_power"); - - if (!pr || (off != 0)) - goto end; - - p += sprintf(p, "active state: C%d\n", - pr->power.state); - - p += sprintf(p, "default state: C%d\n", - pr->power.default_state); - - p += sprintf(p, "bus master activity: %08x\n", - pr->power.bm_activity); - - p += sprintf(p, "states:\n"); - - for (i=1; ipower.state?'*':' '), i); - - if (!pr->power.states[i].valid) { - p += sprintf(p, "\n"); - continue; - } - - if (pr->power.states[i].promotion.state) - p += sprintf(p, "promotion[C%d] ", - pr->power.states[i].promotion.state); - else - p += sprintf(p, "promotion[--] "); - - if (pr->power.states[i].demotion.state) - p += sprintf(p, "demotion[C%d] ", - pr->power.states[i].demotion.state); - else - p += sprintf(p, "demotion[--] "); - - p += sprintf(p, "latency[%03d] usage[%08d]\n", - pr->power.states[i].latency, - pr->power.states[i].usage); - } - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_processor_read_performance ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_processor *pr = (struct acpi_processor *) data; - char *p = page; - int len = 0; - int i = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_read_performance"); - - if (!pr || (off != 0)) - goto end; - - if (!pr->flags.performance) { - p += sprintf(p, "\n"); - goto end; - } - - p += sprintf(p, "state count: %d\n", - pr->performance.state_count); - - p += sprintf(p, "active state: P%d\n", - pr->performance.state); - - p += sprintf(p, "states:\n"); - - for (i=0; iperformance.state_count; i++) - p += sprintf(p, " %cP%d: %d Mhz, %d mW, %d uS\n", - (i == pr->performance.state?'*':' '), i, - (u32) pr->performance.states[i].core_frequency, - (u32) pr->performance.states[i].power, - (u32) pr->performance.states[i].transition_latency); - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_processor_write_performance ( - struct file *file, - const char *buffer, - unsigned long count, - void *data) -{ - int result = 0; - struct acpi_processor *pr = (struct acpi_processor *) data; - char state_string[12] = {'\0'}; - - ACPI_FUNCTION_TRACE("acpi_processor_write_performance"); - - if (!pr || (count > sizeof(state_string) - 1)) - return_VALUE(-EINVAL); - - if (copy_from_user(state_string, buffer, count)) - return_VALUE(-EFAULT); - - state_string[count] = '\0'; - - result = acpi_processor_set_performance(pr, - simple_strtoul(state_string, NULL, 0)); - if (0 != result) - return_VALUE(result); - - return_VALUE(count); -} - - -static int -acpi_processor_read_throttling ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_processor *pr = (struct acpi_processor *) data; - char *p = page; - int len = 0; - int i = 0; - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_read_throttling"); - - if (!pr || (off != 0)) - goto end; - - if (!(pr->throttling.state_count > 0)) { - p += sprintf(p, "\n"); - goto end; - } - - result = acpi_processor_get_throttling(pr); - - if (result) { - p += sprintf(p, "Could not determine current throttling state.\n"); - goto end; - } - - p += sprintf(p, "state count: %d\n", - pr->throttling.state_count); - - p += sprintf(p, "active state: T%d\n", - pr->throttling.state); - - p += sprintf(p, "states:\n"); - - for (i=0; ithrottling.state_count; i++) - p += sprintf(p, " %cT%d: %02d%%\n", - (i == pr->throttling.state?'*':' '), i, - (pr->throttling.states[i].performance?pr->throttling.states[i].performance/10:0)); - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_processor_write_throttling ( - struct file *file, - const char *buffer, - unsigned long count, - void *data) -{ - int result = 0; - struct acpi_processor *pr = (struct acpi_processor *) data; - char state_string[12] = {'\0'}; - - ACPI_FUNCTION_TRACE("acpi_processor_write_throttling"); - - if (!pr || (count > sizeof(state_string) - 1)) - return_VALUE(-EINVAL); - - if (copy_from_user(state_string, buffer, count)) - return_VALUE(-EFAULT); - - state_string[count] = '\0'; - - result = acpi_processor_set_throttling(pr, - simple_strtoul(state_string, NULL, 0)); - if (0 != result) - return_VALUE(result); - - return_VALUE(count); -} - - -static int -acpi_processor_read_limit ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_processor *pr = (struct acpi_processor *) data; - char *p = page; - int len = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_read_limit"); - - if (!pr || (off != 0)) - goto end; - - if (!pr->flags.limit) { - p += sprintf(p, "\n"); - goto end; - } - - p += sprintf(p, "active limit: P%d:T%d\n", - pr->limit.state.px, pr->limit.state.tx); - - p += sprintf(p, "platform limit: P%d:T0\n", - pr->flags.performance?pr->performance.platform_limit:0); - - p += sprintf(p, "user limit: P%d:T%d\n", - pr->limit.user.px, pr->limit.user.tx); - - p += sprintf(p, "thermal limit: P%d:T%d\n", - pr->limit.thermal.px, pr->limit.thermal.tx); - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_processor_write_limit ( - struct file *file, - const char *buffer, - unsigned long count, - void *data) -{ - int result = 0; - struct acpi_processor *pr = (struct acpi_processor *) data; - char limit_string[25] = {'\0'}; - int px = 0; - int tx = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_write_limit"); - - if (!pr || (count > sizeof(limit_string) - 1)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n")); - return_VALUE(-EINVAL); - } - - if (copy_from_user(limit_string, buffer, count)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n")); - return_VALUE(-EFAULT); - } - - limit_string[count] = '\0'; - - if (sscanf(limit_string, "%d:%d", &px, &tx) != 2) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n")); - return_VALUE(-EINVAL); - } - - if (pr->flags.performance) { - if ((px < pr->performance.platform_limit) - || (px > (pr->performance.state_count - 1))) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid px\n")); - return_VALUE(-EINVAL); - } - pr->limit.user.px = px; - } - - if (pr->flags.throttling) { - if ((tx < 0) || (tx > (pr->throttling.state_count - 1))) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid tx\n")); - return_VALUE(-EINVAL); - } - pr->limit.user.tx = tx; - } - - result = acpi_processor_apply_limit(pr); - - return_VALUE(count); -} - - -static int -acpi_processor_add_fs ( - struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - - ACPI_FUNCTION_TRACE("acpi_processor_add_fs"); - - if (!acpi_processor_dir) { - acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, - acpi_root_dir); - if (!acpi_processor_dir) - return_VALUE(-ENODEV); - } - - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_processor_dir); - if (!acpi_device_dir(device)) - return_VALUE(-ENODEV); - } - - /* 'info' [R] */ - entry = create_proc_entry(ACPI_PROCESSOR_FILE_INFO, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_PROCESSOR_FILE_INFO)); - else { - entry->read_proc = acpi_processor_read_info; - entry->data = acpi_driver_data(device); - } - - /* 'power' [R] */ - entry = create_proc_entry(ACPI_PROCESSOR_FILE_POWER, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_PROCESSOR_FILE_POWER)); - else { - entry->read_proc = acpi_processor_read_power; - entry->data = acpi_driver_data(device); - } - - /* 'performance' [R/W] */ - entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_PROCESSOR_FILE_PERFORMANCE)); - else { - entry->read_proc = acpi_processor_read_performance; - entry->write_proc = acpi_processor_write_performance; - entry->data = acpi_driver_data(device); - } - - /* 'throttling' [R/W] */ - entry = create_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_PROCESSOR_FILE_THROTTLING)); - else { - entry->read_proc = acpi_processor_read_throttling; - entry->write_proc = acpi_processor_write_throttling; - entry->data = acpi_driver_data(device); - } - - /* 'limit' [R/W] */ - entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_PROCESSOR_FILE_LIMIT)); - else { - entry->read_proc = acpi_processor_read_limit; - entry->write_proc = acpi_processor_write_limit; - entry->data = acpi_driver_data(device); - } - - return_VALUE(0); -} - - -static int -acpi_processor_remove_fs ( - struct acpi_device *device) -{ - ACPI_FUNCTION_TRACE("acpi_processor_remove_fs"); - - if (!acpi_processor_dir) - return_VALUE(-ENODEV); - - if (acpi_device_dir(device)) - remove_proc_entry(acpi_device_bid(device), acpi_processor_dir); - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ - -static int -acpi_processor_get_info ( - struct acpi_processor *pr) -{ - acpi_status status = 0; - acpi_object object = {0}; - acpi_buffer buffer = {sizeof(acpi_object), &object}; - static int cpu_count = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_get_info"); - - if (!pr) - return_VALUE(-EINVAL); - -#ifdef CONFIG_SMP - if (smp_num_cpus > 1) - errata.smp = smp_num_cpus; -#endif - - acpi_processor_errata(pr); - - /* - * Check to see if we have bus mastering arbitration control. This - * is required for proper C3 usage (to maintain cache coherency). - */ - if (acpi_fadt.V1_pm2_cnt_blk && acpi_fadt.pm2_cnt_len) { - pr->flags.bm_control = 1; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Bus mastering arbitration control present\n")); - } - else - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "No bus mastering arbitration control\n")); - - /* - * Evalute the processor object. Note that it is common on SMP to - * have the first (boot) processor with a valid PBLK address while - * all others have a NULL address. - */ - status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error evaluating processor object\n")); - return_VALUE(-ENODEV); - } - - /* - * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. - * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c - */ - pr->id = cpu_count++; - pr->acpi_id = object.processor.proc_id; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, - pr->acpi_id)); - - if (!object.processor.pblk_address) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n")); - else if (object.processor.pblk_length < 6) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid PBLK length [%d]\n", - object.processor.pblk_length)); - else { - pr->throttling.address = object.processor.pblk_address; - pr->throttling.duty_offset = acpi_fadt.duty_offset; - pr->throttling.duty_width = acpi_fadt.duty_width; - pr->power.states[ACPI_STATE_C2].address = - object.processor.pblk_address + 4; - pr->power.states[ACPI_STATE_C3].address = - object.processor.pblk_address + 5; - } - - acpi_processor_get_power_info(pr); - acpi_processor_get_performance_info(pr); - acpi_processor_get_throttling_info(pr); - acpi_processor_get_limit_info(pr); - - return_VALUE(0); -} - - -static void -acpi_processor_notify ( - acpi_handle handle, - u32 event, - void *data) -{ - int result = 0; - struct acpi_processor *pr = (struct acpi_processor *) data; - struct acpi_device *device = NULL; - - ACPI_FUNCTION_TRACE("acpi_processor_notify"); - - if (!pr) - return_VOID; - - if (0 != acpi_bus_get_device(pr->handle, &device)) - return_VOID; - - switch (event) { - case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: - result = acpi_processor_get_platform_limit(pr); - if (0 == result) - acpi_processor_apply_limit(pr); - - acpi_bus_generate_event(device, event, - pr->performance.platform_limit); - break; - case ACPI_PROCESSOR_NOTIFY_POWER: - /* TBD */ - acpi_bus_generate_event(device, event, 0); - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Unsupported event [0x%x]\n", event)); - break; - } - - return_VOID; -} - - -static int -acpi_processor_add ( - struct acpi_device *device) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_processor *pr = NULL; - u32 i = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_add"); - - if (!device) - return_VALUE(-EINVAL); - - pr = kmalloc(sizeof(struct acpi_processor), GFP_KERNEL); - if (!pr) - return_VALUE(-ENOMEM); - memset(pr, 0, sizeof(struct acpi_processor)); - - pr->handle = device->handle; - sprintf(acpi_device_name(device), "%s", ACPI_PROCESSOR_DEVICE_NAME); - sprintf(acpi_device_class(device), "%s", ACPI_PROCESSOR_CLASS); - acpi_driver_data(device) = pr; - - result = acpi_processor_get_info(pr); - if (0 != result) - goto end; - - result = acpi_processor_add_fs(device); - if (0 != result) - goto end; - - status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, - acpi_processor_notify, pr); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error installing notify handler\n")); - result = -ENODEV; - goto end; - } - - processors[pr->id] = pr; - - /* - * Install the idle handler if processor power management is supported. - * Note that the default idle handler (default_idle) will be used on - * platforms that only support C1. - */ - if ((pr->id == 0) && (pr->flags.power)) { - pm_idle_save = pm_idle; - pm_idle = acpi_processor_idle; - } - - printk(KERN_INFO PREFIX "%s [%s] (supports", - acpi_device_name(device), acpi_device_bid(device)); - for (i=1; ipower.states[i].valid) - printk(" C%d", i); - if (pr->flags.performance) - printk(", %d performance states", pr->performance.state_count); - if (pr->flags.throttling) - printk(", %d throttling states", pr->throttling.state_count); - printk(")\n"); - -end: - if (0 != result) { - acpi_processor_remove_fs(device); - kfree(pr); - } - - return_VALUE(result); -} - - -static int -acpi_processor_remove ( - struct acpi_device *device, - int type) -{ - acpi_status status = AE_OK; - struct acpi_processor *pr = NULL; - - ACPI_FUNCTION_TRACE("acpi_processor_remove"); - - if (!device || !acpi_driver_data(device)) - return_VALUE(-EINVAL); - - pr = (struct acpi_processor *) acpi_driver_data(device); - - /* Unregister the idle handler when processor #0 is removed. */ - if (pr->id == 0) - pm_idle = pm_idle_save; - - status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, - acpi_processor_notify); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error removing notify handler\n")); - return_VALUE(-ENODEV); - } - - acpi_processor_remove_fs(device); - - processors[pr->id] = NULL; - - kfree(pr); - - return_VALUE(0); -} - - -static int __init -acpi_processor_init (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_init"); - - memset(&processors, 0, sizeof(processors)); - memset(&errata, 0, sizeof(errata)); - - result = acpi_bus_register_driver(&acpi_processor_driver); - if (0 > result) - return_VALUE(-ENODEV); - - return_VALUE(0); -} - - -static void __exit -acpi_processor_exit (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_exit"); - - result = acpi_bus_unregister_driver(&acpi_processor_driver); - if (0 == result) - remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); - - return_VOID; -} - - -module_init(acpi_processor_init); -module_exit(acpi_processor_exit); diff -Nru a/drivers/acpi/acpi_system.c b/drivers/acpi/acpi_system.c --- a/drivers/acpi/acpi_system.c Sun Jun 2 18:44:58 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1270 +0,0 @@ -/* - * acpi_system.c - ACPI System Driver ($Revision: 45 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "acpi_bus.h" -#include "acpi_drivers.h" - -#ifdef CONFIG_X86 -#ifdef CONFIG_ACPI_SLEEP -#include -#endif -#endif - - -#define _COMPONENT ACPI_SYSTEM_COMPONENT -ACPI_MODULE_NAME ("acpi_system") - -#define PREFIX "ACPI: " - -extern FADT_DESCRIPTOR acpi_fadt; - -static int acpi_system_add (struct acpi_device *device); -static int acpi_system_remove (struct acpi_device *device, int type); - -static struct acpi_driver acpi_system_driver = { - name: ACPI_SYSTEM_DRIVER_NAME, - class: ACPI_SYSTEM_CLASS, - ids: ACPI_SYSTEM_HID, - ops: { - add: acpi_system_add, - remove: acpi_system_remove - }, -}; - -struct acpi_system -{ - acpi_handle handle; - u8 states[ACPI_S_STATE_COUNT]; -}; - -/* Global vars for handling event proc entry */ -static spinlock_t acpi_system_event_lock = SPIN_LOCK_UNLOCKED; -int event_is_open = 0; -extern struct list_head acpi_bus_event_list; -extern wait_queue_head_t acpi_bus_event_queue; - -/* -------------------------------------------------------------------------- - System Sleep - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_PM - -static void -acpi_power_off (void) -{ - acpi_enter_sleep_state_prep(ACPI_STATE_S5); - ACPI_DISABLE_IRQS(); - acpi_enter_sleep_state(ACPI_STATE_S5); -} - -#endif /*CONFIG_PM*/ - - -#ifdef CONFIG_ACPI_SLEEP - -/** - * acpi_system_restore_state - OS-specific restoration of state - * @state: sleep state we're exiting - * - * Note that if we're coming back from S4, the memory image should have already - * been loaded from the disk and is already in place. (Otherwise how else would we - * be here?). - */ -acpi_status -acpi_system_restore_state ( - u32 state) -{ - /* restore processor state - * We should only be here if we're coming back from STR or STD. - * And, in the case of the latter, the memory image should have already - * been loaded from disk. - */ - if (state > ACPI_STATE_S1) - acpi_restore_state_mem(); - - /* wait for power to come back */ - mdelay(10); -#ifdef HAVE_NEW_DEVICE_MODEL - /* turn all the devices back on */ - device_resume(RESUME_POWER_ON); - - /* enable interrupts once again */ - ACPI_ENABLE_IRQS(); - - /* restore device context */ - device_resume(RESUME_RESTORE_STATE); -#endif - - if (dmi_broken & BROKEN_INIT_AFTER_S1) { - printk("Broken toshiba laptop -> kicking interrupts\n"); - init_8259A(0); - } - - return AE_OK; -} - -/** - * acpi_system_save_state - save OS specific state and power down devices - * @state: sleep state we're entering. - * - * This handles saving all context to memory, and possibly disk. - * First, we call to the device driver layer to save device state. - * Once we have that, we save whatevery processor and kernel state we - * need to memory. - * If we're entering S4, we then write the memory image to disk. - * - * Only then is it safe for us to power down devices, since we may need - * the disks and upstream buses to write to. - */ -acpi_status -acpi_system_save_state( - u32 state) -{ - int error = 0; - -#ifdef HAVE_NEW_DEVICE_MODEL - /* Send notification to devices that they will be suspended. - * If any device or driver cannot make the transition, either up - * or down, we'll get an error back. - */ - error = device_suspend(state, SUSPEND_NOTIFY); - if (error) - return AE_ERROR; -#endif - if (state < ACPI_STATE_S5) { - -#ifdef HAVE_NEW_DEVICE_MODEL - /* Tell devices to stop I/O and actually save their state. - * It is theoretically possible that something could fail, - * so handle that gracefully.. - */ - error = device_suspend(state, SUSPEND_SAVE_STATE); - if (error) { - /* tell devices to restore state if they have - * it saved and to start taking I/O requests. - */ - device_resume(RESUME_RESTORE_STATE); - return error; - } -#endif - - /* flush caches */ - wbinvd(); - - /* Do arch specific saving of state. */ - if (state > ACPI_STATE_S1) { - error = acpi_save_state_mem(); - - if (!error && (state == ACPI_STATE_S4)) - error = acpi_save_state_disk(); - -#ifdef HAVE_NEW_DEVICE_MODEL - if (error) { - device_resume(RESUME_RESTORE_STATE); - return error; - } -#endif - } - } -#ifdef HAVE_NEW_DEVICE_MODEL - /* disable interrupts - * Note that acpi_suspend -- our caller -- will do this once we return. - * But, we want it done early, so we don't get any suprises during - * the device suspend sequence. - */ - ACPI_DISABLE_IRQS(); - - /* Unconditionally turn off devices. - * Obvious if we enter a sleep state. - * If entering S5 (soft off), this should put devices in a - * quiescent state. - */ - error = device_suspend(state, SUSPEND_POWER_DOWN); - - /* We're pretty screwed if we got an error from this. - * We try to recover by simply calling our own restore_state - * function; see above for definition. - * - * If it's S5 though, go through with it anyway.. - */ - if (error && state != ACPI_STATE_S5) - acpi_system_restore_state(state); -#endif - return error ? AE_ERROR : AE_OK; -} - - -/**************************************************************************** - * - * FUNCTION: acpi_system_suspend - * - * PARAMETERS: %state: Sleep state to enter. - * - * RETURN: acpi_status, whether or not we successfully entered and - * exited sleep. - * - * DESCRIPTION: Perform OS-specific action to enter sleep state. - * This is the final step in going to sleep, per spec. If we - * know we're coming back (i.e. not entering S5), we save the - * processor flags. [ We'll have to save and restore them anyway, - * so we use the arch-agnostic save_flags and restore_flags - * here.] We then set the place to return to in arch-specific - * globals using arch_set_return_point. Finally, we call the - * ACPI function to write the proper values to I/O ports. - * - ****************************************************************************/ - -acpi_status -acpi_system_suspend( - u32 state) -{ - acpi_status status = AE_ERROR; - unsigned long flags = 0; - - save_flags(flags); - - switch (state) - { - case ACPI_STATE_S1: - barrier(); - status = acpi_enter_sleep_state(state); - break; - - case ACPI_STATE_S2: - case ACPI_STATE_S3: - do_suspend_magic(0); - break; - } - - acpi_restore_register_state(); - restore_flags(flags); - - return status; -} - - -/** - * acpi_suspend - OS-agnostic system suspend/resume support (S? states) - * @state: state we're entering - * - */ -acpi_status -acpi_suspend ( - u32 state) -{ - acpi_status status; - - /* get out if state is invalid */ - if (state < ACPI_STATE_S1 || state > ACPI_STATE_S5) - return AE_ERROR; - - freeze_processes(); - - /* do we have a wakeup address for S2 and S3? */ - if (state == ACPI_STATE_S2 || state == ACPI_STATE_S3) { - if (!acpi_wakeup_address) - return AE_ERROR; - acpi_set_firmware_waking_vector((ACPI_PHYSICAL_ADDRESS) acpi_wakeup_address); - } - - acpi_enter_sleep_state_prep(state); - - status = acpi_system_save_state(state); - if (!ACPI_SUCCESS(status)) - return status; - - /* disable interrupts and flush caches */ - ACPI_DISABLE_IRQS(); - wbinvd(); - - /* perform OS-specific sleep actions */ - status = acpi_system_suspend(state); - - /* Even if we failed to go to sleep, all of the devices are in an suspended - * mode. So, we run these unconditionaly to make sure we have a usable system - * no matter what. - */ - acpi_system_restore_state(state); - acpi_leave_sleep_state(state); - - /* make sure interrupts are enabled */ - ACPI_ENABLE_IRQS(); - - /* reset firmware waking vector */ - acpi_set_firmware_waking_vector((ACPI_PHYSICAL_ADDRESS) 0); - - thaw_processes(); - - return status; -} - -#endif /* CONFIG_ACPI_SLEEP */ - - -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -#include -#include - - -static int -acpi_system_read_info ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_system *system = (struct acpi_system *) data; - char *p = page; - int size = 0; - u32 i = 0; - - ACPI_FUNCTION_TRACE("acpi_system_read_info"); - - if (!system || (off != 0)) - goto end; - - p += sprintf(p, "version: %x\n", ACPI_CA_VERSION); - - p += sprintf(p, "states: "); - for (i=0; istates[i]) - p += sprintf(p, "S%d ", i); - } - p += sprintf(p, "\n"); - -end: - size = (p - page); - if (size <= off+count) *eof = 1; - *start = page + off; - size -= off; - if (size>count) size = count; - if (size<0) size = 0; - - return_VALUE(size); -} - -static int acpi_system_open_event(struct inode *inode, struct file *file); -static ssize_t acpi_system_read_event (struct file*, char*, size_t, loff_t*); -static int acpi_system_close_event(struct inode *inode, struct file *file); -static unsigned int acpi_system_poll_event(struct file *file, poll_table *wait); - - -static struct file_operations acpi_system_event_ops = { - open: acpi_system_open_event, - read: acpi_system_read_event, - release: acpi_system_close_event, - poll: acpi_system_poll_event, -}; - -static int -acpi_system_open_event(struct inode *inode, struct file *file) -{ - spin_lock_irq (&acpi_system_event_lock); - - if(event_is_open) - goto out_busy; - - event_is_open = 1; - - spin_unlock_irq (&acpi_system_event_lock); - return 0; - -out_busy: - spin_unlock_irq (&acpi_system_event_lock); - return -EBUSY; -} - -static ssize_t -acpi_system_read_event ( - struct file *file, - char *buffer, - size_t count, - loff_t *ppos) -{ - int result = 0; - char outbuf[ACPI_MAX_STRING]; - int size = 0; - struct acpi_bus_event event; - - ACPI_FUNCTION_TRACE("acpi_system_read_event"); - - memset(&event, 0, sizeof(struct acpi_bus_event)); - - if (count < ACPI_MAX_STRING) - goto end; - - if ((file->f_flags & O_NONBLOCK) - && (list_empty(&acpi_bus_event_list))) - return_VALUE(-EAGAIN); - - result = acpi_bus_receive_event(&event); - if (0 != result) { - size = sprintf(outbuf, "error\n"); - goto end; - } - - size = sprintf(outbuf, "%s %s %08x %08x\n", - event.device_class?event.device_class:"", - event.bus_id?event.bus_id:"", - event.type, - event.data); - -end: - if (copy_to_user(buffer, outbuf, size)) - return_VALUE(-EFAULT); - - *ppos += size; - - return_VALUE(size); -} - -static int -acpi_system_close_event(struct inode *inode, struct file *file) -{ - spin_lock_irq (&acpi_system_event_lock); - event_is_open = 0; - spin_unlock_irq (&acpi_system_event_lock); - return 0; -} - -static unsigned int -acpi_system_poll_event( - struct file *file, - poll_table *wait) -{ - poll_wait(file, &acpi_bus_event_queue, wait); - if (!list_empty(&acpi_bus_event_list)) - return POLLIN | POLLRDNORM; - return 0; -} - -static ssize_t acpi_system_read_dsdt (struct file*, char*, size_t, loff_t*); - -static struct file_operations acpi_system_dsdt_ops = { - read: acpi_system_read_dsdt, -}; - -static ssize_t -acpi_system_read_dsdt ( - struct file *file, - char *buffer, - size_t count, - loff_t *ppos) -{ - acpi_status status = AE_OK; - acpi_buffer dsdt = {ACPI_ALLOCATE_BUFFER, NULL}; - void *data = 0; - size_t size = 0; - - ACPI_FUNCTION_TRACE("acpi_system_read_dsdt"); - - status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - if (*ppos < dsdt.length) { - data = dsdt.pointer + file->f_pos; - size = dsdt.length - file->f_pos; - if (size > count) - size = count; - if (copy_to_user(buffer, data, size)) { - kfree(dsdt.pointer); - return_VALUE(-EFAULT); - } - } - - kfree(dsdt.pointer); - - *ppos += size; - - return_VALUE(size); -} - - -static ssize_t acpi_system_read_fadt (struct file*, char*, size_t, loff_t*); - -static struct file_operations acpi_system_fadt_ops = { - read: acpi_system_read_fadt, -}; - -static ssize_t -acpi_system_read_fadt ( - struct file *file, - char *buffer, - size_t count, - loff_t *ppos) -{ - acpi_status status = AE_OK; - acpi_buffer fadt = {ACPI_ALLOCATE_BUFFER, NULL}; - void *data = 0; - size_t size = 0; - - ACPI_FUNCTION_TRACE("acpi_system_read_fadt"); - - status = acpi_get_table(ACPI_TABLE_FADT, 1, &fadt); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - if (*ppos < fadt.length) { - data = fadt.pointer + file->f_pos; - size = fadt.length - file->f_pos; - if (size > count) - size = count; - if (copy_to_user(buffer, data, size)) { - kfree(fadt.pointer); - return_VALUE(-EFAULT); - } - } - - kfree(fadt.pointer); - - *ppos += size; - - return_VALUE(size); -} - - -#ifdef ACPI_DEBUG - -static int -acpi_system_read_debug ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - char *p = page; - int size = 0; - - if (off != 0) - goto end; - - switch ((unsigned long) data) { - case 0: - p += sprintf(p, "0x%08x\n", acpi_dbg_layer); - break; - case 1: - p += sprintf(p, "0x%08x\n", acpi_dbg_level); - break; - default: - p += sprintf(p, "Invalid debug option\n"); - break; - } - -end: - size = (p - page); - if (size <= off+count) *eof = 1; - *start = page + off; - size -= off; - if (size>count) size = count; - if (size<0) size = 0; - - return size; -} - - -static int -acpi_system_write_debug ( - struct file *file, - const char *buffer, - unsigned long count, - void *data) -{ - char debug_string[12] = {'\0'}; - - ACPI_FUNCTION_TRACE("acpi_system_write_debug"); - - if (count > sizeof(debug_string) - 1) - return_VALUE(-EINVAL); - - if (copy_from_user(debug_string, buffer, count)) - return_VALUE(-EFAULT); - - debug_string[count] = '\0'; - - switch ((unsigned long) data) { - case 0: - acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0); - break; - case 1: - acpi_dbg_level = simple_strtoul(debug_string, NULL, 0); - break; - default: - return_VALUE(-EINVAL); - } - - return_VALUE(count); -} - -#endif /* ACPI_DEBUG */ - - -#ifdef CONFIG_ACPI_SLEEP - -static int -acpi_system_read_sleep ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_system *system = (struct acpi_system *) data; - char *p = page; - int size; - int i; - - ACPI_FUNCTION_TRACE("acpi_system_read_sleep"); - - if (!system || (off != 0)) - goto end; - - for (i = 0; i <= ACPI_STATE_S5; i++) { - if (system->states[i]) - p += sprintf(p,"S%d ", i); - } - - p += sprintf(p, "\n"); - -end: - size = (p - page); - if (size <= off+count) *eof = 1; - *start = page + off; - size -= off; - if (size>count) size = count; - if (size<0) size = 0; - - return_VALUE(size); -} - - -static int -acpi_system_write_sleep ( - struct file *file, - const char *buffer, - unsigned long count, - void *data) -{ - acpi_status status = AE_OK; - struct acpi_system *system = (struct acpi_system *) data; - char state_string[12] = {'\0'}; - u32 state = 0; - - ACPI_FUNCTION_TRACE("acpi_system_write_sleep"); - - if (!system || (count > sizeof(state_string) - 1)) - return_VALUE(-EINVAL); - - if (copy_from_user(state_string, buffer, count)) - return_VALUE(-EFAULT); - - state_string[count] = '\0'; - - state = simple_strtoul(state_string, NULL, 0); - - if (!system->states[state]) - return_VALUE(-ENODEV); - -#ifdef CONFIG_SOFTWARE_SUSPEND - if (state == 4) { - software_suspend(); - return_VALUE(count); - } -#endif - status = acpi_suspend(state); - - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - return_VALUE(count); -} - - -static int -acpi_system_read_alarm ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *context) -{ - char *p = page; - int size = 0; - u32 sec, min, hr; - u32 day, mo, yr; - - ACPI_FUNCTION_TRACE("acpi_system_read_alarm"); - - if (off != 0) - goto end; - - spin_lock(&rtc_lock); - - sec = CMOS_READ(RTC_SECONDS_ALARM); - min = CMOS_READ(RTC_MINUTES_ALARM); - hr = CMOS_READ(RTC_HOURS_ALARM); - -#if 0 /* If we ever get an FACP with proper values... */ - if (acpi_gbl_FADT->day_alrm) - day = CMOS_READ(acpi_gbl_FADT->day_alrm); - else - day = CMOS_READ(RTC_DAY_OF_MONTH); - if (acpi_gbl_FADT->mon_alrm) - mo = CMOS_READ(acpi_gbl_FADT->mon_alrm); - else - mo = CMOS_READ(RTC_MONTH);; - if (acpi_gbl_FADT->century) - yr = CMOS_READ(acpi_gbl_FADT->century) * 100 + CMOS_READ(RTC_YEAR); - else - yr = CMOS_READ(RTC_YEAR); -#else - day = CMOS_READ(RTC_DAY_OF_MONTH); - mo = CMOS_READ(RTC_MONTH); - yr = CMOS_READ(RTC_YEAR); -#endif - - spin_unlock(&rtc_lock); - - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hr); - BCD_TO_BIN(day); - BCD_TO_BIN(mo); - BCD_TO_BIN(yr); - - p += sprintf(p,"%4.4u-", yr); - p += (mo > 12) ? sprintf(p, "**-") : sprintf(p, "%2.2u-", mo); - p += (day > 31) ? sprintf(p, "** ") : sprintf(p, "%2.2u ", day); - p += (hr > 23) ? sprintf(p, "**:") : sprintf(p, "%2.2u:", hr); - p += (min > 59) ? sprintf(p, "**:") : sprintf(p, "%2.2u:", min); - p += (sec > 59) ? sprintf(p, "**\n") : sprintf(p, "%2.2u\n", sec); - - end: - size = p - page; - if (size < count) *eof = 1; - else if (size > count) size = count; - if (size < 0) size = 0; - *start = page; - - return_VALUE(size); -} - - -static int -get_date_field ( - char **p, - u32 *value) -{ - char *next = NULL; - char *string_end = NULL; - int result = -EINVAL; - - /* - * Try to find delimeter, only to insert null. The end of the - * string won't have one, but is still valid. - */ - next = strpbrk(*p, "- :"); - if (next) - *next++ = '\0'; - - *value = simple_strtoul(*p, &string_end, 10); - - /* Signal success if we got a good digit */ - if (string_end != *p) - result = 0; - - if (next) - *p = next; - - return result; -} - - -static int -acpi_system_write_alarm ( - struct file *file, - const char *buffer, - unsigned long count, - void *data) -{ - int result = 0; - char alarm_string[30] = {'\0'}; - char *p = alarm_string; - u32 sec, min, hr, day, mo, yr; - int adjust = 0; - unsigned char rtc_control = 0; - - ACPI_FUNCTION_TRACE("acpi_system_write_alarm"); - - if (count > sizeof(alarm_string) - 1) - return_VALUE(-EINVAL); - - if (copy_from_user(alarm_string, buffer, count)) - return_VALUE(-EFAULT); - - alarm_string[count] = '\0'; - - /* check for time adjustment */ - if (alarm_string[0] == '+') { - p++; - adjust = 1; - } - - if ((result = get_date_field(&p, &yr))) - goto end; - if ((result = get_date_field(&p, &mo))) - goto end; - if ((result = get_date_field(&p, &day))) - goto end; - if ((result = get_date_field(&p, &hr))) - goto end; - if ((result = get_date_field(&p, &min))) - goto end; - if ((result = get_date_field(&p, &sec))) - goto end; - - if (sec > 59) { - min += 1; - sec -= 60; - } - if (min > 59) { - hr += 1; - min -= 60; - } - if (hr > 23) { - day += 1; - hr -= 24; - } - if (day > 31) { - mo += 1; - day -= 31; - } - if (mo > 12) { - yr += 1; - mo -= 12; - } - - spin_lock_irq(&rtc_lock); - - rtc_control = CMOS_READ(RTC_CONTROL); - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(yr); - BIN_TO_BCD(mo); - BIN_TO_BCD(day); - BIN_TO_BCD(hr); - BIN_TO_BCD(min); - BIN_TO_BCD(sec); - } - - if (adjust) { - yr += CMOS_READ(RTC_YEAR); - mo += CMOS_READ(RTC_MONTH); - day += CMOS_READ(RTC_DAY_OF_MONTH); - hr += CMOS_READ(RTC_HOURS); - min += CMOS_READ(RTC_MINUTES); - sec += CMOS_READ(RTC_SECONDS); - } - - spin_unlock_irq(&rtc_lock); - - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BCD_TO_BIN(yr); - BCD_TO_BIN(mo); - BCD_TO_BIN(day); - BCD_TO_BIN(hr); - BCD_TO_BIN(min); - BCD_TO_BIN(sec); - } - - if (sec > 59) { - min++; - sec -= 60; - } - if (min > 59) { - hr++; - min -= 60; - } - if (hr > 23) { - day++; - hr -= 24; - } - if (day > 31) { - mo++; - day -= 31; - } - if (mo > 12) { - yr++; - mo -= 12; - } - if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(yr); - BIN_TO_BCD(mo); - BIN_TO_BCD(day); - BIN_TO_BCD(hr); - BIN_TO_BCD(min); - BIN_TO_BCD(sec); - } - - spin_lock_irq(&rtc_lock); - - /* write the fields the rtc knows about */ - CMOS_WRITE(hr, RTC_HOURS_ALARM); - CMOS_WRITE(min, RTC_MINUTES_ALARM); - CMOS_WRITE(sec, RTC_SECONDS_ALARM); - - /* - * If the system supports an enhanced alarm it will have non-zero - * offsets into the CMOS RAM here -- which for some reason are pointing - * to the RTC area of memory. - */ -#if 0 - if (acpi_gbl_FADT->day_alrm) - CMOS_WRITE(day, acpi_gbl_FADT->day_alrm); - if (acpi_gbl_FADT->mon_alrm) - CMOS_WRITE(mo, acpi_gbl_FADT->mon_alrm); - if (acpi_gbl_FADT->century) - CMOS_WRITE(yr/100, acpi_gbl_FADT->century); -#endif - /* enable the rtc alarm interrupt */ - if (!(rtc_control & RTC_AIE)) { - rtc_control |= RTC_AIE; - CMOS_WRITE(rtc_control,RTC_CONTROL); - CMOS_READ(RTC_INTR_FLAGS); - } - - spin_unlock_irq(&rtc_lock); - - acpi_hw_bit_register_write(ACPI_BITREG_RT_CLOCK_ENABLE, 1, ACPI_MTX_LOCK); - - file->f_pos += count; - - result = 0; -end: - return_VALUE(result ? result : count); -} - -#endif /*CONFIG_ACPI_SLEEP*/ - - -static int -acpi_system_add_fs ( - struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - - ACPI_FUNCTION_TRACE("acpi_system_add_fs"); - - if (!device) - return_VALUE(-EINVAL); - - /* 'info' [R] */ - entry = create_proc_entry(ACPI_SYSTEM_FILE_INFO, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_SYSTEM_FILE_INFO)); - else { - entry->read_proc = acpi_system_read_info; - entry->data = acpi_driver_data(device); - } - - /* 'dsdt' [R] */ - entry = create_proc_entry(ACPI_SYSTEM_FILE_DSDT, - S_IRUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_SYSTEM_FILE_DSDT)); - else - entry->proc_fops = &acpi_system_dsdt_ops; - - /* 'fadt' [R] */ - entry = create_proc_entry(ACPI_SYSTEM_FILE_FADT, - S_IRUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_SYSTEM_FILE_FADT)); - else - entry->proc_fops = &acpi_system_fadt_ops; - - /* 'event' [R] */ - entry = create_proc_entry(ACPI_SYSTEM_FILE_EVENT, - S_IRUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_SYSTEM_FILE_EVENT)); - else - entry->proc_fops = &acpi_system_event_ops; - -#ifdef CONFIG_ACPI_SLEEP - - /* 'sleep' [R/W]*/ - entry = create_proc_entry(ACPI_SYSTEM_FILE_SLEEP, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_SYSTEM_FILE_SLEEP)); - else { - entry->read_proc = acpi_system_read_sleep; - entry->write_proc = acpi_system_write_sleep; - entry->data = acpi_driver_data(device); - } - - /* 'alarm' [R/W] */ - entry = create_proc_entry(ACPI_SYSTEM_FILE_ALARM, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_SYSTEM_FILE_ALARM)); - else { - entry->read_proc = acpi_system_read_alarm; - entry->write_proc = acpi_system_write_alarm; - entry->data = acpi_driver_data(device); - } - -#endif /*CONFIG_ACPI_SLEEP*/ - -#ifdef ACPI_DEBUG - - /* 'debug_layer' [R/W] */ - entry = create_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_SYSTEM_FILE_DEBUG_LAYER)); - else { - entry->read_proc = acpi_system_read_debug; - entry->write_proc = acpi_system_write_debug; - entry->data = (void *) 0; - } - - /* 'debug_level' [R/W] */ - entry = create_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LEVEL, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_SYSTEM_FILE_DEBUG_LEVEL)); - else { - entry->read_proc = acpi_system_read_debug; - entry->write_proc = acpi_system_write_debug; - entry->data = (void *) 1; - } - -#endif /*ACPI_DEBUG*/ - - return_VALUE(0); -} - - -static int -acpi_system_remove_fs ( - struct acpi_device *device) -{ - ACPI_FUNCTION_TRACE("acpi_system_remove_fs"); - - if (!device) - return_VALUE(-EINVAL); - - remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_device_dir(device)); - remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_device_dir(device)); - remove_proc_entry(ACPI_SYSTEM_FILE_EVENT, acpi_device_dir(device)); -#ifdef CONFIG_ACPI_SLEEP - remove_proc_entry(ACPI_SYSTEM_FILE_SLEEP, acpi_device_dir(device)); - remove_proc_entry(ACPI_SYSTEM_FILE_ALARM, acpi_device_dir(device)); -#endif -#ifdef ACPI_DEBUG - remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, - acpi_device_dir(device)); - remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LEVEL, - acpi_device_dir(device)); -#endif - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ - -#if defined(CONFIG_MAGIC_SYSRQ) && defined(CONFIG_PM) - -/* Simple wrapper calling power down function. */ -static void acpi_sysrq_power_off(int key, struct pt_regs *pt_regs, - struct kbd_struct *kbd, struct tty_struct *tty) -{ - acpi_power_off(); -} - -struct sysrq_key_op sysrq_acpi_poweroff_op = { - handler: &acpi_sysrq_power_off, - help_msg: "Off", - action_msg: "Power Off\n" -}; - -#endif /* CONFIG_MAGIC_SYSRQ */ - -static int -acpi_system_add ( - struct acpi_device *device) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_system *system = NULL; - u8 i = 0; - - ACPI_FUNCTION_TRACE("acpi_system_add"); - - if (!device) - return_VALUE(-EINVAL); - - system = kmalloc(sizeof(struct acpi_system), GFP_KERNEL); - if (!system) - return_VALUE(-ENOMEM); - memset(system, 0, sizeof(struct acpi_system)); - - system->handle = device->handle; - sprintf(acpi_device_name(device), "%s", ACPI_SYSTEM_DEVICE_NAME); - sprintf(acpi_device_class(device), "%s", ACPI_SYSTEM_CLASS); - acpi_driver_data(device) = system; - - result = acpi_system_add_fs(device); - if (0 != result) - goto end; - - printk(KERN_INFO PREFIX "%s [%s] (supports", - acpi_device_name(device), acpi_device_bid(device)); - for (i=0; istates[i] = 1; - printk(" S%d", i); - } - } - printk(")\n"); -#ifdef CONFIG_SOFTWARE_SUSPEND - printk(KERN_INFO "Software suspend => we can do S4."); - system->states[4] = 1; -#endif - -#ifdef CONFIG_PM - /* Install the soft-off (S5) handler. */ - if (system->states[ACPI_STATE_S5]) { - pm_power_off = acpi_power_off; - register_sysrq_key('o', &sysrq_acpi_poweroff_op); - } -#endif - -end: - if (0 != result) - kfree(system); - - return_VALUE(result); -} - - -static int -acpi_system_remove ( - struct acpi_device *device, - int type) -{ - struct acpi_system *system = NULL; - - ACPI_FUNCTION_TRACE("acpi_system_remove"); - - if (!device || !acpi_driver_data(device)) - return_VALUE(-EINVAL); - - system = (struct acpi_system *) acpi_driver_data(device); - -#ifdef CONFIG_PM - /* Remove the soft-off (S5) handler. */ - if (system->states[ACPI_STATE_S5]) { - unregister_sysrq_key('o', &sysrq_acpi_poweroff_op); - pm_power_off = NULL; - } -#endif - - acpi_system_remove_fs(device); - - kfree(system); - - return 0; -} - - -int __init -acpi_system_init (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_system_init"); - - result = acpi_bus_register_driver(&acpi_system_driver); - if (0 > result) - return_VALUE(-ENODEV); - - return_VALUE(0); -} - - -void __exit -acpi_system_exit (void) -{ - ACPI_FUNCTION_TRACE("acpi_system_exit"); - acpi_bus_unregister_driver(&acpi_system_driver); - return_VOID; -} diff -Nru a/drivers/acpi/acpi_tables.c b/drivers/acpi/acpi_tables.c --- a/drivers/acpi/acpi_tables.c Sun Jun 2 18:44:57 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,515 +0,0 @@ -/* - * acpi_tables.c - ACPI Boot-Time Table Parsing - * - * Copyright (C) 2001 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PREFIX "ACPI: " - -#define ACPI_MAX_TABLES ACPI_TABLE_COUNT - -static char *acpi_table_signatures[ACPI_TABLE_COUNT] = { - [ACPI_TABLE_UNKNOWN] = "????", - [ACPI_APIC] = "APIC", - [ACPI_BOOT] = "BOOT", - [ACPI_DBGP] = "DBGP", - [ACPI_DSDT] = "DSDT", - [ACPI_ECDT] = "ECDT", - [ACPI_ETDT] = "ETDT", - [ACPI_FACP] = "FACP", - [ACPI_FACS] = "FACS", - [ACPI_OEMX] = "OEM", - [ACPI_PSDT] = "PSDT", - [ACPI_SBST] = "SBST", - [ACPI_SLIT] = "SLIT", - [ACPI_SPCR] = "SPCR", - [ACPI_SRAT] = "SRAT", - [ACPI_SSDT] = "SSDT", - [ACPI_SPMI] = "SPMI" -}; - -/* System Description Table (RSDT/XSDT) */ -struct acpi_table_sdt { - unsigned long pa; /* Physical Address */ - unsigned long count; /* Table count */ - struct { - unsigned long pa; - enum acpi_table_id id; - unsigned long size; - } entry[ACPI_MAX_TABLES]; -} __attribute__ ((packed)); - -static struct acpi_table_sdt sdt; - -acpi_madt_entry_handler madt_handlers[ACPI_MADT_ENTRY_COUNT]; - -struct acpi_boot_flags acpi_boot = {1, 0}; /* Enabled by default */ - - -void -acpi_table_print ( - struct acpi_table_header *header, - unsigned long phys_addr) -{ - char *name = NULL; - - if (!header) - return; - - /* Some table signatures aren't good table names */ - - if (0 == strncmp((char *) &header->signature, - acpi_table_signatures[ACPI_APIC], - sizeof(header->signature))) { - name = "MADT"; - } - else if (0 == strncmp((char *) &header->signature, - acpi_table_signatures[ACPI_FACP], - sizeof(header->signature))) { - name = "FADT"; - } - else - name = header->signature; - - printk(KERN_INFO PREFIX "%.4s (v%3.3d %6.6s %8.8s %5.5d.%5.5d) @ 0x%p\n", - name, header->revision, header->oem_id, - header->oem_table_id, header->oem_revision >> 16, - header->oem_revision & 0xffff, (void *) phys_addr); -} - - -void -acpi_table_print_madt_entry ( - acpi_table_entry_header *header) -{ - if (!header) - return; - - switch (header->type) { - - case ACPI_MADT_LAPIC: - { - struct acpi_table_lapic *p = - (struct acpi_table_lapic*) header; - printk(KERN_INFO PREFIX "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n", - p->acpi_id, p->id, p->flags.enabled?"enabled":"disabled"); - } - break; - - case ACPI_MADT_IOAPIC: - { - struct acpi_table_ioapic *p = - (struct acpi_table_ioapic*) header; - printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] global_irq_base[0x%x])\n", - p->id, p->address, p->global_irq_base); - } - break; - - case ACPI_MADT_INT_SRC_OVR: - { - struct acpi_table_int_src_ovr *p = - (struct acpi_table_int_src_ovr*) header; - printk(KERN_INFO PREFIX "INT_SRC_OVR (bus[%d] irq[0x%x] global_irq[0x%x] polarity[0x%x] trigger[0x%x])\n", - p->bus, p->bus_irq, p->global_irq, p->flags.polarity, p->flags.trigger); - } - break; - - case ACPI_MADT_NMI_SRC: - { - struct acpi_table_nmi_src *p = - (struct acpi_table_nmi_src*) header; - printk(KERN_INFO PREFIX "NMI_SRC (polarity[0x%x] trigger[0x%x] global_irq[0x%x])\n", - p->flags.polarity, p->flags.trigger, p->global_irq); - } - break; - - case ACPI_MADT_LAPIC_NMI: - { - struct acpi_table_lapic_nmi *p = - (struct acpi_table_lapic_nmi*) header; - printk(KERN_INFO PREFIX "LAPIC_NMI (acpi_id[0x%02x] polarity[0x%x] trigger[0x%x] lint[0x%x])\n", - p->acpi_id, p->flags.polarity, p->flags.trigger, p->lint); - } - break; - - case ACPI_MADT_LAPIC_ADDR_OVR: - { - struct acpi_table_lapic_addr_ovr *p = - (struct acpi_table_lapic_addr_ovr*) header; - printk(KERN_INFO PREFIX "LAPIC_ADDR_OVR (address[0x%016Lx])\n", - p->address); - } - break; - - case ACPI_MADT_IOSAPIC: - { - struct acpi_table_iosapic *p = - (struct acpi_table_iosapic*) header; - printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] global_irq_base[0x%x] address[0x%016Lx])\n", - p->id, p->global_irq_base, p->address); - } - break; - - case ACPI_MADT_LSAPIC: - { - struct acpi_table_lsapic *p = - (struct acpi_table_lsapic*) header; - printk(KERN_INFO PREFIX "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n", - p->acpi_id, p->id, p->eid, p->flags.enabled?"enabled":"disabled"); - } - break; - - case ACPI_MADT_PLAT_INT_SRC: - { - struct acpi_table_plat_int_src *p = - (struct acpi_table_plat_int_src*) header; - printk(KERN_INFO PREFIX "PLAT_INT_SRC (polarity[0x%x] trigger[0x%x] type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n", - p->flags.polarity, p->flags.trigger, p->type, p->id, p->eid, p->iosapic_vector, p->global_irq); - } - break; - - default: - printk(KERN_WARNING PREFIX "Found unsupported MADT entry (type = 0x%x)\n", - header->type); - break; - } -} - - -static int -acpi_table_compute_checksum ( - void *table_pointer, - unsigned long length) -{ - u8 *p = (u8 *) table_pointer; - unsigned long remains = length; - unsigned long sum = 0; - - if (!p || !length) - return -EINVAL; - - while (remains--) - sum += *p++; - - return (sum & 0xFF); -} - - -int __init -acpi_table_parse_madt ( - enum acpi_table_id id, - acpi_madt_entry_handler handler) -{ - struct acpi_table_madt *madt = NULL; - acpi_table_entry_header *entry = NULL; - unsigned long count = 0; - unsigned long madt_end = 0; - int i = 0; - - if (!handler) - return -EINVAL; - - /* Locate the MADT (if exists). There should only be one. */ - - for (i = 0; i < sdt.count; i++) { - if (sdt.entry[i].id != ACPI_APIC) - continue; - madt = (struct acpi_table_madt *) - __acpi_map_table(sdt.entry[i].pa, sdt.entry[i].size); - if (!madt) { - printk(KERN_WARNING PREFIX "Unable to map MADT\n"); - return -ENODEV; - } - break; - } - - if (!madt) { - printk(KERN_WARNING PREFIX "MADT not present\n"); - return -ENODEV; - } - - madt_end = (unsigned long) madt + sdt.entry[i].size; - - /* Parse all entries looking for a match. */ - - entry = (acpi_table_entry_header *) - ((unsigned long) madt + sizeof(struct acpi_table_madt)); - - while (((unsigned long) entry) < madt_end) { - if (entry->type == id) { - count++; - handler(entry); - } - entry = (acpi_table_entry_header *) - ((unsigned long) entry += entry->length); - } - - return count; -} - - -int __init -acpi_table_parse ( - enum acpi_table_id id, - acpi_table_handler handler) -{ - int count = 0; - int i = 0; - - if (!handler) - return -EINVAL; - - for (i = 0; i < sdt.count; i++) { - if (sdt.entry[i].id != id) - continue; - handler(sdt.entry[i].pa, sdt.entry[i].size); - count++; - } - - return count; -} - - -static int __init -acpi_table_get_sdt ( - struct acpi_table_rsdp *rsdp) -{ - struct acpi_table_header *header = NULL; - int i, id = 0; - - if (!rsdp) - return -EINVAL; - - /* First check XSDT (but only on ACPI 2.0-compatible systems) */ - - if ((rsdp->revision >= 2) && - (((struct acpi20_table_rsdp*)rsdp)->xsdt_address)) { - - struct acpi_table_xsdt *mapped_xsdt = NULL; - - sdt.pa = ((struct acpi20_table_rsdp*)rsdp)->xsdt_address; - - header = (struct acpi_table_header *) - __acpi_map_table(sdt.pa, sizeof(struct acpi_table_header)); - - if (!header) { - printk(KERN_WARNING PREFIX "Unable to map XSDT header\n"); - return -ENODEV; - } - - if (strncmp(header->signature, "XSDT", 4)) { - printk(KERN_WARNING PREFIX "XSDT signature incorrect\n"); - return -ENODEV; - } - - sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 3; - if (sdt.count > ACPI_MAX_TABLES) { - printk(KERN_WARNING PREFIX "Truncated %lu XSDT entries\n", - (ACPI_MAX_TABLES - sdt.count)); - sdt.count = ACPI_MAX_TABLES; - } - - mapped_xsdt = (struct acpi_table_xsdt *) - __acpi_map_table(sdt.pa, header->length); - if (!mapped_xsdt) { - printk(KERN_WARNING PREFIX "Unable to map XSDT\n"); - return -ENODEV; - } - - header = &mapped_xsdt->header; - - for (i = 0; i < sdt.count; i++) - sdt.entry[i].pa = (unsigned long) mapped_xsdt->entry[i]; - } - - /* Then check RSDT */ - - else if (rsdp->rsdt_address) { - - struct acpi_table_rsdt *mapped_rsdt = NULL; - - sdt.pa = rsdp->rsdt_address; - - header = (struct acpi_table_header *) - __acpi_map_table(sdt.pa, sizeof(struct acpi_table_header)); - if (!header) { - printk(KERN_WARNING PREFIX "Unable to map RSDT header\n"); - return -ENODEV; - } - - if (strncmp(header->signature, "RSDT", 4)) { - printk(KERN_WARNING PREFIX "RSDT signature incorrect\n"); - return -ENODEV; - } - - sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 2; - if (sdt.count > ACPI_MAX_TABLES) { - printk(KERN_WARNING PREFIX "Truncated %lu RSDT entries\n", - (ACPI_TABLE_COUNT - sdt.count)); - sdt.count = ACPI_MAX_TABLES; - } - - mapped_rsdt = (struct acpi_table_rsdt *) - __acpi_map_table(sdt.pa, header->length); - if (!mapped_rsdt) { - printk(KERN_WARNING PREFIX "Unable to map RSDT\n"); - return -ENODEV; - } - - header = &mapped_rsdt->header; - - for (i = 0; i < sdt.count; i++) - sdt.entry[i].pa = (unsigned long) mapped_rsdt->entry[i]; - } - - else { - printk(KERN_WARNING PREFIX "No System Description Table (RSDT/XSDT) specified in RSDP\n"); - return -ENODEV; - } - - acpi_table_print(header, sdt.pa); - - for (i = 0; i < sdt.count; i++) { - - header = (struct acpi_table_header *) - __acpi_map_table(sdt.entry[i].pa, - sizeof(struct acpi_table_header)); - if (!header) - continue; - - acpi_table_print(header, sdt.entry[i].pa); - - if (0 != acpi_table_compute_checksum(header, header->length)) { - printk(KERN_WARNING " >>> ERROR: Invalid checksum\n"); - continue; - } - - sdt.entry[i].size = header->length; - - for (id = 0; id < ACPI_TABLE_COUNT; id++) { - if (0 == strncmp((char *) &header->signature, - acpi_table_signatures[id], - sizeof(header->signature))) { - sdt.entry[i].id = id; - } - } - } - - return 0; -} - - -static void __init -acpi_table_parse_cmdline ( - char *cmdline) -{ - char *p = NULL; - - /* NOTE: We're called too early in the boot process to use __setup */ - - if (!cmdline || !(p = strstr(cmdline, "acpi_boot="))) - return; - - p += 10; - - while (*p && (*p != ' ')) { - if (0 == memcmp(p, "madt", 4)) { - printk(KERN_INFO PREFIX "MADT processing enabled\n"); - acpi_boot.madt = 1; - p += 4; - } - else if (0 == memcmp(p, "on", 2)) { - printk(KERN_INFO PREFIX "Boot-time table processing enabled\n"); - acpi_boot.madt = 1; - p += 2; - } - else if (0 == memcmp(p, "off", 2)) { - printk(KERN_INFO PREFIX "Boot-time table processing disabled\n"); - acpi_boot.madt = 0; - p += 3; - } - else - p++; - - if (*p == ',') - p ++; - } -} - - -int __init -acpi_table_init ( - char *cmdline) -{ - struct acpi_table_rsdp *rsdp = NULL; - unsigned long rsdp_phys = 0; - int result = 0; - - memset(&sdt, 0, sizeof(struct acpi_table_sdt)); - memset(&madt_handlers, 0, sizeof(madt_handlers)); - - acpi_table_parse_cmdline(cmdline); - - /* Locate and map the Root System Description Table (RSDP) */ - - if ((0 != acpi_find_rsdp(&rsdp_phys)) || !rsdp_phys) { - printk(KERN_ERR PREFIX "Unable to locate RSDP\n"); - return -ENODEV; - } - - rsdp = (struct acpi_table_rsdp *) __va(rsdp_phys); - if (!rsdp) { - printk(KERN_WARNING PREFIX "Unable to map RSDP\n"); - return -ENODEV; - } - - printk(KERN_INFO PREFIX "RSDP (v%3.3d %6.6s ) @ 0x%p\n", - rsdp->revision, rsdp->oem_id, (void *) rsdp_phys); - - if (rsdp->revision < 2) - result = acpi_table_compute_checksum(rsdp, sizeof(struct acpi_table_rsdp)); - else - result = acpi_table_compute_checksum(rsdp, ((struct acpi20_table_rsdp *)rsdp)->length); - - if (0 != result) { - printk(KERN_WARNING " >>> ERROR: Invalid checksum\n"); - return -ENODEV; - } - - /* Locate and map the System Description table (RSDT/XSDT) */ - - if (0 != acpi_table_get_sdt(rsdp)) - return -ENODEV; - - return 0; -} diff -Nru a/drivers/acpi/acpi_thermal.c b/drivers/acpi/acpi_thermal.c --- a/drivers/acpi/acpi_thermal.c Sun Jun 2 18:44:57 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1318 +0,0 @@ -/* - * acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 36 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This driver fully implements the ACPI thermal policy as described in the - * ACPI 2.0 Specification. - * - * TBD: 1. Implement passive cooling hysteresis. - * 2. Enhance passive cooling (CPU) states/limit interface to support - * concepts of 'multiple limiters', upper/lower limits, etc. - * - */ - -#include -#include -#include -#include -#include -#include -#include "acpi_bus.h" -#include "acpi_drivers.h" - - -#define _COMPONENT ACPI_THERMAL_COMPONENT -ACPI_MODULE_NAME ("acpi_thermal") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME); -MODULE_LICENSE("GPL"); - -static int tzp = 0; -MODULE_PARM(tzp, "i"); -MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); - -#define PREFIX "ACPI: " - - -#define ACPI_THERMAL_MAX_ACTIVE 10 - -#define KELVIN_TO_CELSIUS(t) ((t-2732+5)/10) - -static int acpi_thermal_add (struct acpi_device *device); -static int acpi_thermal_remove (struct acpi_device *device, int type); - -static struct acpi_driver acpi_thermal_driver = { - name: ACPI_THERMAL_DRIVER_NAME, - class: ACPI_THERMAL_CLASS, - ids: ACPI_THERMAL_HID, - ops: { - add: acpi_thermal_add, - remove: acpi_thermal_remove, - }, -}; - -struct acpi_thermal_state { - u8 critical:1; - u8 hot:1; - u8 passive:1; - u8 active:1; - u8 reserved:4; - int active_index; -}; - -struct acpi_thermal_state_flags { - u8 valid:1; - u8 enabled:1; - u8 reserved:6; -}; - -struct acpi_thermal_critical { - struct acpi_thermal_state_flags flags; - unsigned long temperature; -}; - -struct acpi_thermal_hot { - struct acpi_thermal_state_flags flags; - unsigned long temperature; -}; - -struct acpi_thermal_passive { - struct acpi_thermal_state_flags flags; - unsigned long temperature; - unsigned long tc1; - unsigned long tc2; - unsigned long tsp; - struct acpi_handle_list devices; -}; - -struct acpi_thermal_active { - struct acpi_thermal_state_flags flags; - unsigned long temperature; - struct acpi_handle_list devices; -}; - -struct acpi_thermal_trips { - struct acpi_thermal_critical critical; - struct acpi_thermal_hot hot; - struct acpi_thermal_passive passive; - struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE]; -}; - -struct acpi_thermal_flags { - u8 cooling_mode:1; /* _SCP */ - u8 devices:1; /* _TZD */ - u8 reserved:6; -}; - -struct acpi_thermal { - acpi_handle handle; - acpi_bus_id name; - unsigned long temperature; - unsigned long last_temperature; - unsigned long polling_frequency; - u8 cooling_mode; - struct acpi_thermal_flags flags; - struct acpi_thermal_state state; - struct acpi_thermal_trips trips; - struct acpi_handle_list devices; - struct timer_list timer; -}; - - -/* -------------------------------------------------------------------------- - Thermal Zone Management - -------------------------------------------------------------------------- */ - -static int -acpi_thermal_get_temperature ( - struct acpi_thermal *tz) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE("acpi_thermal_get_temperature"); - - if (!tz) - return_VALUE(-EINVAL); - - tz->last_temperature = tz->temperature; - - status = acpi_evaluate_integer(tz->handle, "_TMP", NULL, &tz->temperature); - if (ACPI_FAILURE(status)) - return -ENODEV; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n", tz->temperature)); - - return_VALUE(0); -} - - -static int -acpi_thermal_get_polling_frequency ( - struct acpi_thermal *tz) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE("acpi_thermal_get_polling_frequency"); - - if (!tz) - return_VALUE(-EINVAL); - - status = acpi_evaluate_integer(tz->handle, "_TZP", NULL, &tz->polling_frequency); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n", tz->polling_frequency)); - - return_VALUE(0); -} - - -static int -acpi_thermal_set_polling ( - struct acpi_thermal *tz, - int seconds) -{ - ACPI_FUNCTION_TRACE("acpi_thermal_set_polling"); - - if (!tz) - return_VALUE(-EINVAL); - - tz->polling_frequency = seconds * 10; /* Convert value to deci-seconds */ - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency set to %lu seconds\n", tz->polling_frequency)); - - return_VALUE(0); -} - - -static int -acpi_thermal_set_cooling_mode ( - struct acpi_thermal *tz, - int mode) -{ - acpi_status status = AE_OK; - acpi_object arg0 = {ACPI_TYPE_INTEGER}; - acpi_object_list arg_list= {1, &arg0}; - acpi_handle handle = NULL; - - ACPI_FUNCTION_TRACE("acpi_thermal_set_cooling_mode"); - - if (!tz) - return_VALUE(-EINVAL); - - status = acpi_get_handle(tz->handle, "_SCP", &handle); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n")); - return_VALUE(-ENODEV); - } - - arg0.integer.value = mode; - - status = acpi_evaluate(handle, NULL, &arg_list, NULL); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - tz->cooling_mode = mode; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n", - mode?"passive":"active")); - - return_VALUE(0); -} - - -static int -acpi_thermal_get_trip_points ( - struct acpi_thermal *tz) -{ - acpi_status status = AE_OK; - int i = 0; - - ACPI_FUNCTION_TRACE("acpi_thermal_get_trip_points"); - - if (!tz) - return_VALUE(-EINVAL); - - /* Critical Shutdown (required) */ - - status = acpi_evaluate_integer(tz->handle, "_CRT", NULL, - &tz->trips.critical.temperature); - if (ACPI_FAILURE(status)) { - tz->trips.critical.flags.valid = 0; - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No critical threshold\n")); - return -ENODEV; - } - else { - tz->trips.critical.flags.valid = 1; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found critical threshold [%lu]\n", tz->trips.critical.temperature)); - } - - /* Critical Sleep (optional) */ - - status = acpi_evaluate_integer(tz->handle, "_HOT", NULL, &tz->trips.hot.temperature); - if (ACPI_FAILURE(status)) { - tz->trips.hot.flags.valid = 0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n")); - } - else { - tz->trips.hot.flags.valid = 1; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n", tz->trips.hot.temperature)); - } - - /* Passive: Processors (optional) */ - - status = acpi_evaluate_integer(tz->handle, "_PSV", NULL, &tz->trips.passive.temperature); - if (ACPI_FAILURE(status)) { - tz->trips.passive.flags.valid = 0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n")); - } - else { - tz->trips.passive.flags.valid = 1; - - status = acpi_evaluate_integer(tz->handle, "_TC1", NULL, &tz->trips.passive.tc1); - if (ACPI_FAILURE(status)) - tz->trips.passive.flags.valid = 0; - - status = acpi_evaluate_integer(tz->handle, "_TC2", NULL, &tz->trips.passive.tc2); - if (ACPI_FAILURE(status)) - tz->trips.passive.flags.valid = 0; - - status = acpi_evaluate_integer(tz->handle, "_TSP", NULL, &tz->trips.passive.tsp); - if (ACPI_FAILURE(status)) - tz->trips.passive.flags.valid = 0; - - status = acpi_evaluate_reference(tz->handle, "_PSL", NULL, &tz->trips.passive.devices); - if (ACPI_FAILURE(status)) - tz->trips.passive.flags.valid = 0; - - if (!tz->trips.passive.flags.valid) - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid passive threshold\n")); - else - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found passive threshold [%lu]\n", tz->trips.passive.temperature)); - } - - /* Active: Fans, etc. (optional) */ - - for (i=0; ihandle, name, NULL, &tz->trips.active[i].temperature); - if (ACPI_FAILURE(status)) - break; - - name[2] = 'L'; - status = acpi_evaluate_reference(tz->handle, name, NULL, &tz->trips.active[i].devices); - if (ACPI_SUCCESS(status)) { - tz->trips.active[i].flags.valid = 1; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found active threshold [%d]:[%lu]\n", i, tz->trips.active[i].temperature)); - } - else - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid active threshold [%d]\n", i)); - } - - return_VALUE(0); -} - - -static int -acpi_thermal_get_devices ( - struct acpi_thermal *tz) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE("acpi_thermal_get_devices"); - - if (!tz) - return_VALUE(-EINVAL); - - status = acpi_evaluate_reference(tz->handle, "_TZD", NULL, &tz->devices); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - return_VALUE(0); -} - - -static int -acpi_thermal_call_usermode ( - char *path) -{ - char *argv[2] = {NULL, NULL}; - char *envp[3] = {NULL, NULL, NULL}; - - ACPI_FUNCTION_TRACE("acpi_thermal_call_usermode"); - - if (!path) - return_VALUE(-EINVAL);; - - argv[0] = path; - - /* minimal command environment */ - envp[0] = "HOME=/"; - envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; - - call_usermodehelper(argv[0], argv, envp); - - return_VALUE(0); -} - - -static int -acpi_thermal_critical ( - struct acpi_thermal *tz) -{ - int result = 0; - struct acpi_device *device = NULL; - - ACPI_FUNCTION_TRACE("acpi_thermal_critical"); - - if (!tz || !tz->trips.critical.flags.valid) - return_VALUE(-EINVAL); - - if (tz->temperature >= tz->trips.critical.temperature) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Critical trip point\n")); - tz->trips.critical.flags.enabled = 1; - } - else if (tz->trips.critical.flags.enabled) - tz->trips.critical.flags.enabled = 0; - - result = acpi_bus_get_device(tz->handle, &device); - if (0 != result) - return_VALUE(result); - - acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled); - - acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF); - - return_VALUE(0); -} - - -static int -acpi_thermal_hot ( - struct acpi_thermal *tz) -{ - int result = 0; - struct acpi_device *device = NULL; - - ACPI_FUNCTION_TRACE("acpi_thermal_hot"); - - if (!tz || !tz->trips.hot.flags.valid) - return_VALUE(-EINVAL); - - if (tz->temperature >= tz->trips.hot.temperature) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Hot trip point\n")); - tz->trips.hot.flags.enabled = 1; - } - else if (tz->trips.hot.flags.enabled) - tz->trips.hot.flags.enabled = 0; - - result = acpi_bus_get_device(tz->handle, &device); - if (0 != result) - return_VALUE(result); - - acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled); - - /* TBD: Call user-mode "sleep(S4)" function */ - - return_VALUE(0); -} - - -static int -acpi_thermal_passive ( - struct acpi_thermal *tz) -{ - int result = 0; - struct acpi_thermal_passive *passive = NULL; - int trend = 0; - int i = 0; - - ACPI_FUNCTION_TRACE("acpi_thermal_passive"); - - if (!tz || !tz->trips.passive.flags.valid) - return_VALUE(-EINVAL); - - passive = &(tz->trips.passive); - - /* - * Above Trip? - * ----------- - * Calculate the thermal trend (using the passive cooling equation) - * and modify the performance limit for all passive cooling devices - * accordingly. Note that we assume symmetry. - */ - if (tz->temperature >= passive->temperature) { - trend = (passive->tc1 * (tz->temperature - tz->last_temperature)) + (passive->tc2 * (tz->temperature - passive->temperature)); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n", - trend, passive->tc1, tz->temperature, - tz->last_temperature, passive->tc2, - tz->temperature, passive->temperature)); - /* Heating up? */ - if (trend > 0) - for (i=0; idevices.count; i++) - acpi_processor_set_thermal_limit( - passive->devices.handles[i], - ACPI_PROCESSOR_LIMIT_INCREMENT); - /* Cooling off? */ - else if (trend < 0) - for (i=0; idevices.count; i++) - acpi_processor_set_thermal_limit( - passive->devices.handles[i], - ACPI_PROCESSOR_LIMIT_DECREMENT); - } - - /* - * Below Trip? - * ----------- - * Implement passive cooling hysteresis to slowly increase performance - * and avoid thrashing around the passive trip point. Note that we - * assume symmetry. - */ - else if (tz->trips.passive.flags.enabled) { - for (i=0; idevices.count; i++) - result = acpi_processor_set_thermal_limit( - passive->devices.handles[i], - ACPI_PROCESSOR_LIMIT_DECREMENT); - if (1 == result) { - tz->trips.passive.flags.enabled = 0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Disabling passive cooling (zone is cool)\n")); - } - } - - return_VALUE(0); -} - - -static int -acpi_thermal_active ( - struct acpi_thermal *tz) -{ - int result = 0; - struct acpi_thermal_active *active = NULL; - int i = 0; - int j = 0; - - ACPI_FUNCTION_TRACE("acpi_thermal_active"); - - if (!tz) - return_VALUE(-EINVAL); - - for (i=0; itrips.active[i]); - if (!active || !active->flags.valid) - break; - - /* - * Above Threshold? - * ---------------- - * If not already enabled, turn ON all cooling devices - * associated with this active threshold. - */ - if (tz->temperature >= active->temperature) { - tz->state.active_index = i; - if (!active->flags.enabled) { - for (j = 0; j < active->devices.count; j++) { - result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D0); - if (0 != result) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'on'\n", active->devices.handles[j])); - continue; - } - active->flags.enabled = 1; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'on'\n", active->devices.handles[j])); - } - } - } - /* - * Below Threshold? - * ---------------- - * Turn OFF all cooling devices associated with this - * threshold. - */ - else if (active->flags.enabled) { - for (j = 0; j < active->devices.count; j++) { - result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D3); - if (0 != result) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'off'\n", active->devices.handles[j])); - continue; - } - active->flags.enabled = 0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'off'\n", active->devices.handles[j])); - } - } - } - - return_VALUE(0); -} - - -static void acpi_thermal_check (void *context); - -static void -acpi_thermal_run ( - unsigned long data) -{ - acpi_os_queue_for_execution(OSD_PRIORITY_GPE, acpi_thermal_check, (void *) data); -} - - -static void -acpi_thermal_check ( - void *data) -{ - int result = 0; - struct acpi_thermal *tz = (struct acpi_thermal *) data; - unsigned long sleep_time = 0; - int i = 0; - - ACPI_FUNCTION_TRACE("acpi_thermal_check"); - - if (!tz) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) context.\n")); - return_VOID; - } - - result = acpi_thermal_get_temperature(tz); - if (0 != result) - return_VOID; - - memset(&tz->state, 0, sizeof(tz->state)); - - /* - * Check Trip Points - * ----------------- - * Compare the current temperature to the trip point values to see - * if we've entered one of the thermal policy states. Note that - * this function determines when a state is entered, but the - * individual policy decides when it is exited (e.g. hysteresis). - */ - if ((tz->trips.critical.flags.valid) && (tz->temperature >= tz->trips.critical.temperature)) - tz->trips.critical.flags.enabled = 1; - if ((tz->trips.hot.flags.valid) && (tz->temperature >= tz->trips.hot.temperature)) - tz->trips.hot.flags.enabled = 1; - if ((tz->trips.passive.flags.valid) && (tz->temperature >= tz->trips.passive.temperature)) - tz->trips.passive.flags.enabled = 1; - for (i=0; itrips.active[i].flags.valid) && (tz->temperature >= tz->trips.active[i].temperature)) - tz->trips.active[i].flags.enabled = 1; - - /* - * Invoke Policy - * ------------- - * Separated from the above check to allow individual policy to - * determine when to exit a given state. - */ - if (tz->trips.critical.flags.enabled) - acpi_thermal_critical(tz); - if (tz->trips.hot.flags.enabled) - acpi_thermal_hot(tz); - if (tz->trips.passive.flags.enabled) - acpi_thermal_passive(tz); - if (tz->trips.active[0].flags.enabled) - acpi_thermal_active(tz); - - /* - * Calculate State - * --------------- - * Again, separated from the above two to allow independent policy - * decisions. - */ - if (tz->trips.critical.flags.enabled) - tz->state.critical = 1; - if (tz->trips.hot.flags.enabled) - tz->state.hot = 1; - if (tz->trips.passive.flags.enabled) - tz->state.passive = 1; - for (i=0; itrips.active[i].flags.enabled) - tz->state.active = 1; - - /* - * Calculate Sleep Time - * -------------------- - * If we're in the passive state, use _TSP's value. Otherwise - * use the default polling frequency (e.g. _TZP). If no polling - * frequency is specified then we'll wait forever (at least until - * a thermal event occurs). Note that _TSP and _TZD values are - * given in 1/10th seconds (we must covert to milliseconds). - */ - if (tz->state.passive) - sleep_time = tz->trips.passive.tsp * 100; - else if (tz->polling_frequency > 0) - sleep_time = tz->polling_frequency * 100; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n", - tz->name, tz->temperature, sleep_time)); - - /* - * Schedule Next Poll - * ------------------ - */ - if (!sleep_time) { - if (timer_pending(&(tz->timer))) - del_timer(&(tz->timer)); - } - else { - if (timer_pending(&(tz->timer))) - mod_timer(&(tz->timer), (HZ * sleep_time) / 1000); - else { - tz->timer.data = (unsigned long) tz; - tz->timer.function = acpi_thermal_run; - tz->timer.expires = jiffies + (HZ * sleep_time) / 1000; - add_timer(&(tz->timer)); - } - } - - return_VOID; -} - - -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -#include -#include - -struct proc_dir_entry *acpi_thermal_dir = NULL; - - -static int -acpi_thermal_read_state ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_thermal *tz = (struct acpi_thermal *) data; - char *p = page; - int len = 0; - - ACPI_FUNCTION_TRACE("acpi_thermal_read_state"); - - if (!tz || (off != 0)) - goto end; - - p += sprintf(p, "state: "); - - if (!tz->state.critical && !tz->state.hot && !tz->state.passive && !tz->state.active) - p += sprintf(p, "ok\n"); - else { - if (tz->state.critical) - p += sprintf(p, "critical "); - if (tz->state.hot) - p += sprintf(p, "hot "); - if (tz->state.passive) - p += sprintf(p, "passive "); - if (tz->state.active) - p += sprintf(p, "active[%d]", tz->state.active_index); - p += sprintf(p, "\n"); - } - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_thermal_read_temperature ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - int result = 0; - struct acpi_thermal *tz = (struct acpi_thermal *) data; - char *p = page; - int len = 0; - - ACPI_FUNCTION_TRACE("acpi_thermal_read_temperature"); - - if (!tz || (off != 0)) - goto end; - - result = acpi_thermal_get_temperature(tz); - if (0 != result) - goto end; - - p += sprintf(p, "temperature: %lu C\n", - KELVIN_TO_CELSIUS(tz->temperature)); - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_thermal_read_trip_points ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_thermal *tz = (struct acpi_thermal *) data; - char *p = page; - int len = 0; - int i = 0; - int j = 0; - - ACPI_FUNCTION_TRACE("acpi_thermal_read_trip_points"); - - if (!tz || (off != 0)) - goto end; - - if (tz->trips.critical.flags.valid) - p += sprintf(p, "critical (S5): %lu C\n", - KELVIN_TO_CELSIUS(tz->trips.critical.temperature)); - - if (tz->trips.hot.flags.valid) - p += sprintf(p, "hot (S4): %lu C\n", - KELVIN_TO_CELSIUS(tz->trips.hot.temperature)); - - if (tz->trips.passive.flags.valid) { - p += sprintf(p, "passive: %lu C: tc1=%lu tc2=%lu tsp=%lu devices=", - KELVIN_TO_CELSIUS(tz->trips.passive.temperature), - tz->trips.passive.tc1, - tz->trips.passive.tc2, - tz->trips.passive.tsp); - for (j=0; jtrips.passive.devices.count; j++) { - - p += sprintf(p, "0x%p ", tz->trips.passive.devices.handles[j]); - } - p += sprintf(p, "\n"); - } - - for (i=0; itrips.active[i].flags.valid)) - break; - p += sprintf(p, "active[%d]: %lu C: devices=", - i, KELVIN_TO_CELSIUS(tz->trips.active[i].temperature)); - for (j=0; jtrips.active[i].devices.count; j++) - p += sprintf(p, "0x%p ", - tz->trips.active[i].devices.handles[j]); - p += sprintf(p, "\n"); - } - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_thermal_read_cooling_mode ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_thermal *tz = (struct acpi_thermal *) data; - char *p = page; - int len = 0; - - ACPI_FUNCTION_TRACE("acpi_thermal_read_cooling_mode"); - - if (!tz || (off != 0)) - goto end; - - if (!tz->flags.cooling_mode) { - p += sprintf(p, "\n"); - goto end; - } - - p += sprintf(p, "cooling mode: %s\n", - tz->cooling_mode?"passive":"active"); - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_thermal_write_cooling_mode ( - struct file *file, - const char *buffer, - unsigned long count, - void *data) -{ - int result = 0; - struct acpi_thermal *tz = (struct acpi_thermal *) data; - char mode_string[12] = {'\0'}; - - ACPI_FUNCTION_TRACE("acpi_thermal_write_cooling_mode"); - - if (!tz || (count > sizeof(mode_string) - 1)) - return_VALUE(-EINVAL); - - if (!tz->flags.cooling_mode) - return_VALUE(-ENODEV); - - if (copy_from_user(mode_string, buffer, count)) - return_VALUE(-EFAULT); - - mode_string[count] = '\0'; - - result = acpi_thermal_set_cooling_mode(tz, - simple_strtoul(mode_string, NULL, 0)); - if (0 != result) - return_VALUE(result); - - return_VALUE(count); -} - - -static int -acpi_thermal_read_polling ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) -{ - struct acpi_thermal *tz = (struct acpi_thermal *) data; - char *p = page; - int len = 0; - - ACPI_FUNCTION_TRACE("acpi_thermal_read_polling"); - - if (!tz || (off != 0)) - goto end; - - if (!tz->polling_frequency) { - p += sprintf(p, "\n"); - goto end; - } - - p += sprintf(p, "polling frequency: %lu seconds\n", - (tz->polling_frequency / 10)); - -end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); -} - - -static int -acpi_thermal_write_polling ( - struct file *file, - const char *buffer, - unsigned long count, - void *data) -{ - int result = 0; - struct acpi_thermal *tz = (struct acpi_thermal *) data; - char polling_string[12] = {'\0'}; - int seconds = 0; - - ACPI_FUNCTION_TRACE("acpi_thermal_write_polling"); - - if (!tz || (count > sizeof(polling_string) - 1)) - return_VALUE(-EINVAL); - - if (copy_from_user(polling_string, buffer, count)) - return_VALUE(-EFAULT); - - polling_string[count] = '\0'; - - seconds = simple_strtoul(polling_string, NULL, 0); - - result = acpi_thermal_set_polling(tz, seconds); - if (0 != result) - return_VALUE(result); - - acpi_thermal_check(tz); - - return_VALUE(count); -} - - -static int -acpi_thermal_add_fs ( - struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - - ACPI_FUNCTION_TRACE("acpi_thermal_add_fs"); - - if (!acpi_thermal_dir) { - acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, - acpi_root_dir); - if (!acpi_thermal_dir) - return_VALUE(-ENODEV); - } - - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_thermal_dir); - if (!acpi_device_dir(device)) - return_VALUE(-ENODEV); - } - - /* 'state' [R] */ - entry = create_proc_entry(ACPI_THERMAL_FILE_STATE, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_THERMAL_FILE_STATE)); - else { - entry->read_proc = acpi_thermal_read_state; - entry->data = acpi_driver_data(device); - } - - /* 'temperature' [R] */ - entry = create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_THERMAL_FILE_TEMPERATURE)); - else { - entry->read_proc = acpi_thermal_read_temperature; - entry->data = acpi_driver_data(device); - } - - /* 'trip_points' [R] */ - entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_THERMAL_FILE_POLLING_FREQ)); - else { - entry->read_proc = acpi_thermal_read_trip_points; - entry->data = acpi_driver_data(device); - } - - /* 'cooling_mode' [R/W] */ - entry = create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_THERMAL_FILE_COOLING_MODE)); - else { - entry->read_proc = acpi_thermal_read_cooling_mode; - entry->write_proc = acpi_thermal_write_cooling_mode; - entry->data = acpi_driver_data(device); - } - - /* 'polling_frequency' [R/W] */ - entry = create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_THERMAL_FILE_POLLING_FREQ)); - else { - entry->read_proc = acpi_thermal_read_polling; - entry->write_proc = acpi_thermal_write_polling; - entry->data = acpi_driver_data(device); - } - - return_VALUE(0); -} - - -static int -acpi_thermal_remove_fs ( - struct acpi_device *device) -{ - ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs"); - - if (!acpi_thermal_dir) - return_VALUE(-ENODEV); - - if (acpi_device_dir(device)) - remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir); - - return_VALUE(0); -} - - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ - -static void -acpi_thermal_notify ( - acpi_handle handle, - u32 event, - void *data) -{ - struct acpi_thermal *tz = (struct acpi_thermal *) data; - struct acpi_device *device = NULL; - - ACPI_FUNCTION_TRACE("acpi_thermal_notify"); - - if (!tz) - return_VOID; - - if (0 != acpi_bus_get_device(tz->handle, &device)) - return_VOID; - - switch (event) { - case ACPI_THERMAL_NOTIFY_TEMPERATURE: - acpi_thermal_check(tz); - break; - case ACPI_THERMAL_NOTIFY_THRESHOLDS: - acpi_thermal_get_trip_points(tz); - acpi_thermal_check(tz); - acpi_bus_generate_event(device, event, 0); - break; - case ACPI_THERMAL_NOTIFY_DEVICES: - if (tz->flags.devices) - acpi_thermal_get_devices(tz); - acpi_bus_generate_event(device, event, 0); - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Unsupported event [0x%x]\n", event)); - break; - } - - return_VOID; -} - - -static int -acpi_thermal_get_info ( - struct acpi_thermal *tz) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_thermal_get_info"); - - if (!tz) - return_VALUE(-EINVAL); - - /* Get temperature [_TMP] (required) */ - result = acpi_thermal_get_temperature(tz); - if (0 != result) - return_VALUE(result); - - /* Set the cooling mode [_SCP] to active cooling (default) */ - result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE); - if (0 == result) - tz->flags.cooling_mode = 1; - - /* Get trip points [_CRT, _PSV, etc.] (required) */ - result = acpi_thermal_get_trip_points(tz); - if (0 != result) - return_VALUE(result); - - /* Get default polling frequency [_TZP] (optional) */ - if (tzp) - tz->polling_frequency = tzp; - else - acpi_thermal_get_polling_frequency(tz); - - /* Get devices in this thermal zone [_TZD] (optional) */ - result = acpi_thermal_get_devices(tz); - if (0 == result) - tz->flags.devices = 1; - - return_VALUE(0); -} - - -static int -acpi_thermal_add ( - struct acpi_device *device) -{ - int result = 0; - acpi_status status = AE_OK; - struct acpi_thermal *tz = NULL; - - ACPI_FUNCTION_TRACE("acpi_thermal_add"); - - if (!device) - return_VALUE(-EINVAL); - - tz = kmalloc(sizeof(struct acpi_thermal), GFP_KERNEL); - if (!tz) - return_VALUE(-ENOMEM); - memset(tz, 0, sizeof(struct acpi_thermal)); - - tz->handle = device->handle; - sprintf(tz->name, "%s", device->pnp.bus_id); - sprintf(acpi_device_name(device), "%s", ACPI_THERMAL_DEVICE_NAME); - sprintf(acpi_device_class(device), "%s", ACPI_THERMAL_CLASS); - acpi_driver_data(device) = tz; - - result = acpi_thermal_get_info(tz); - if (0 != result) - goto end; - - result = acpi_thermal_add_fs(device); - if (0 != result) - return_VALUE(result); - - acpi_thermal_check(tz); - - status = acpi_install_notify_handler(tz->handle, - ACPI_DEVICE_NOTIFY, acpi_thermal_notify, tz); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error installing notify handler\n")); - result = -ENODEV; - goto end; - } - - init_timer(&tz->timer); - - printk(KERN_INFO PREFIX "%s [%s] (%lu C)\n", - acpi_device_name(device), acpi_device_bid(device), - KELVIN_TO_CELSIUS(tz->temperature)); - -end: - if (result) { - acpi_thermal_remove_fs(device); - kfree(tz); - } - - return_VALUE(result); -} - - -static int -acpi_thermal_remove ( - struct acpi_device *device, - int type) -{ - acpi_status status = AE_OK; - struct acpi_thermal *tz = NULL; - - ACPI_FUNCTION_TRACE("acpi_thermal_remove"); - - if (!device || !acpi_driver_data(device)) - return_VALUE(-EINVAL); - - tz = (struct acpi_thermal *) acpi_driver_data(device); - - if (timer_pending(&(tz->timer))) - del_timer(&(tz->timer)); - - status = acpi_remove_notify_handler(tz->handle, - ACPI_DEVICE_NOTIFY, acpi_thermal_notify); - if (ACPI_FAILURE(status)) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error removing notify handler\n")); - - /* Terminate policy */ - if (tz->trips.passive.flags.valid - && tz->trips.passive.flags.enabled) { - tz->trips.passive.flags.enabled = 0; - acpi_thermal_passive(tz); - } - if (tz->trips.active[0].flags.valid - && tz->trips.active[0].flags.enabled) { - tz->trips.active[0].flags.enabled = 0; - acpi_thermal_active(tz); - } - - acpi_thermal_remove_fs(device); - - return_VALUE(0); -} - - -static int __init -acpi_thermal_init (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_thermal_init"); - - result = acpi_bus_register_driver(&acpi_thermal_driver); - if (0 > result) - return_VALUE(-ENODEV); - - return_VALUE(0); -} - - -static void __exit -acpi_thermal_exit (void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_thermal_exit"); - - result = acpi_bus_unregister_driver(&acpi_thermal_driver); - if (0 == result) - remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); - - return_VOID; -} - - -module_init(acpi_thermal_init); -module_exit(acpi_thermal_exit); diff -Nru a/drivers/acpi/acpi_utils.c b/drivers/acpi/acpi_utils.c --- a/drivers/acpi/acpi_utils.c Sun Jun 2 18:44:57 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,460 +0,0 @@ -/* - * acpi_utils.c - ACPI Utility Functions ($Revision: 5 $) - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include "acpi_bus.h" -#include "acpi_drivers.h" - - -#define _COMPONENT ACPI_BUS_COMPONENT -ACPI_MODULE_NAME ("acpi_utils") - - -/* -------------------------------------------------------------------------- - Object Evaluation Helpers - -------------------------------------------------------------------------- */ - -#ifdef ACPI_DEBUG -#define acpi_util_eval_error(h,p,s) {\ - char prefix[80] = {'\0'};\ - acpi_buffer buffer = {sizeof(prefix), prefix};\ - acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",\ - (char *) prefix, p, acpi_format_exception(s))); } -#else -#define acpi_util_eval_error(h,p,s) -#endif - - -acpi_status -acpi_extract_package ( - acpi_object *package, - acpi_buffer *format, - acpi_buffer *buffer) -{ - u32 size_required = 0; - u32 tail_offset = 0; - char *format_string = NULL; - u32 format_count = 0; - u32 i = 0; - u8 *head = NULL; - u8 *tail = NULL; - - ACPI_FUNCTION_TRACE("acpi_extract_package"); - - if (!package || (package->type != ACPI_TYPE_PACKAGE) || (package->package.count < 1)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'package' argument\n")); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (!format || !format->pointer || (format->length < 1)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'format' argument\n")); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (!buffer) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'buffer' argument\n")); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - format_count = (format->length/sizeof(char)) - 1; - if (format_count > package->package.count) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Format specifies more objects [%d] than exist in package [%d].", format_count, package->package.count)); - return_ACPI_STATUS(AE_BAD_DATA); - } - - format_string = (char*)format->pointer; - - /* - * Calculate size_required. - */ - for (i=0; ipackage.elements[i]); - - if (!element) { - return_ACPI_STATUS(AE_BAD_DATA); - } - - switch (element->type) { - - case ACPI_TYPE_INTEGER: - switch (format_string[i]) { - case 'N': - size_required += sizeof(acpi_integer); - tail_offset += sizeof(acpi_integer); - break; - case 'S': - size_required += sizeof(char*) + sizeof(acpi_integer) + sizeof(char); - tail_offset += sizeof(char*); - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid package element [%d]: got number, expecing [%c].\n", i, format_string[i])); - return_ACPI_STATUS(AE_BAD_DATA); - break; - } - break; - - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - switch (format_string[i]) { - case 'S': - size_required += sizeof(char*) + (element->string.length * sizeof(char)) + sizeof(char); - tail_offset += sizeof(char*); - break; - case 'B': - size_required += sizeof(u8*) + (element->buffer.length * sizeof(u8)); - tail_offset += sizeof(u8*); - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid package element [%d] got string/buffer, expecing [%c].\n", i, format_string[i])); - return_ACPI_STATUS(AE_BAD_DATA); - break; - } - break; - - case ACPI_TYPE_PACKAGE: - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unsupported element at index=%d\n", i)); - /* TBD: handle nested packages... */ - return_ACPI_STATUS(AE_SUPPORT); - break; - } - } - - /* - * Validate output buffer. - */ - if (buffer->length < size_required) { - buffer->length = size_required; - return_ACPI_STATUS(AE_BUFFER_OVERFLOW); - } - else if (buffer->length != size_required || !buffer->pointer) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - head = buffer->pointer; - tail = buffer->pointer + tail_offset; - - /* - * Extract package data. - */ - for (i=0; ipackage.elements[i]); - - if (!element) { - return_ACPI_STATUS(AE_BAD_DATA); - } - - switch (element->type) { - - case ACPI_TYPE_INTEGER: - switch (format_string[i]) { - case 'N': - *((acpi_integer*)head) = element->integer.value; - head += sizeof(acpi_integer); - break; - case 'S': - pointer = (u8**)head; - *pointer = tail; - *((acpi_integer*)tail) = element->integer.value; - head += sizeof(acpi_integer*); - tail += sizeof(acpi_integer); - /* NULL terminate string */ - *tail = (char)0; - tail += sizeof(char); - break; - default: - /* Should never get here */ - break; - } - break; - - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - switch (format_string[i]) { - case 'S': - pointer = (u8**)head; - *pointer = tail; - memcpy(tail, element->string.pointer, element->string.length); - head += sizeof(char*); - tail += element->string.length * sizeof(char); - /* NULL terminate string */ - *tail = (char)0; - tail += sizeof(char); - break; - case 'B': - pointer = (u8**)head; - *pointer = tail; - memcpy(tail, element->buffer.pointer, element->buffer.length); - head += sizeof(u8*); - tail += element->buffer.length * sizeof(u8); - break; - default: - /* Should never get here */ - break; - } - break; - - case ACPI_TYPE_PACKAGE: - /* TBD: handle nested packages... */ - default: - /* Should never get here */ - break; - } - } - - return_ACPI_STATUS(AE_OK); -} - - -acpi_status -acpi_evaluate ( - acpi_handle handle, - acpi_string pathname, - acpi_object_list *arguments, - acpi_buffer *buffer) -{ - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE("acpi_evaluate"); - - /* If caller provided a buffer it must be unallocated/zero'd. */ - if (buffer && (buffer->length != 0 || buffer->pointer)) - return_ACPI_STATUS(AE_BAD_PARAMETER); - - /* - * Evalute object. The first attempt is just to get the size of the - * object data (that is unless there's no return data); the second - * gets the data. - */ - status = acpi_evaluate_object(handle, pathname, arguments, buffer); - - if (ACPI_SUCCESS(status)) { - return_ACPI_STATUS(status); - } - - else if (buffer && (status == AE_BUFFER_OVERFLOW)) { - - /* Gotta allocate - CALLER MUST FREE! */ - buffer->pointer = kmalloc(buffer->length, GFP_KERNEL); - if (!buffer->pointer) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - memset(buffer->pointer, 0, buffer->length); - - /* Re-evaluate - this time it should work. */ - status = acpi_evaluate_object(handle, pathname, arguments, - buffer); - } - - if (ACPI_FAILURE(status)) { - if (status != AE_NOT_FOUND) - acpi_util_eval_error(handle, pathname, status); - if (buffer && buffer->pointer) { - kfree(buffer->pointer); - buffer->length = 0; - } - } - - return_ACPI_STATUS(status); -} - - -acpi_status -acpi_evaluate_integer ( - acpi_handle handle, - acpi_string pathname, - acpi_object_list *arguments, - unsigned long *data) -{ - acpi_status status = AE_OK; - acpi_object element; - acpi_buffer buffer = {sizeof(acpi_object), &element}; - - ACPI_FUNCTION_TRACE("acpi_evaluate_integer"); - - if (!data) - return_ACPI_STATUS(AE_BAD_PARAMETER); - - status = acpi_evaluate_object(handle, pathname, arguments, &buffer); - if (ACPI_FAILURE(status)) { - acpi_util_eval_error(handle, pathname, status); - return_ACPI_STATUS(status); - } - - if (element.type != ACPI_TYPE_INTEGER) { - acpi_util_eval_error(handle, pathname, AE_BAD_DATA); - return_ACPI_STATUS(AE_BAD_DATA); - } - - *data = element.integer.value; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data)); - - return_ACPI_STATUS(AE_OK); -} - - -#if 0 -acpi_status -acpi_evaluate_string ( - acpi_handle handle, - acpi_string pathname, - acpi_object_list *arguments, - acpi_string *data) -{ - acpi_status status = AE_OK; - acpi_object *element = NULL; - acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - - ACPI_FUNCTION_TRACE("acpi_evaluate_string"); - - if (!data) - return_ACPI_STATUS(AE_BAD_PARAMETER); - - status = acpi_evaluate_object(handle, pathname, arguments, &buffer); - if (ACPI_FAILURE(status)) { - acpi_util_eval_error(handle, pathname, status); - return_ACPI_STATUS(status); - } - - element = (acpi_object *) buffer.pointer; - - if ((element->type != ACPI_TYPE_STRING) - || (element->type != ACPI_TYPE_BUFFER) - || !element->string.length) { - acpi_util_eval_error(handle, pathname, AE_BAD_DATA); - return_ACPI_STATUS(AE_BAD_DATA); - } - - *data = kmalloc(element->string.length + 1, GFP_KERNEL); - if (!data) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Memory allocation error\n")); - return_VALUE(-ENOMEM); - } - memset(*data, 0, element->string.length + 1); - - memcpy(*data, element->string.pointer, element->string.length); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%s]\n", *data)); - - return_ACPI_STATUS(AE_OK); -} -#endif - - -acpi_status -acpi_evaluate_reference ( - acpi_handle handle, - acpi_string pathname, - acpi_object_list *arguments, - struct acpi_handle_list *list) -{ - acpi_status status = AE_OK; - acpi_object *package = NULL; - acpi_object *element = NULL; - acpi_buffer buffer = {0, NULL}; - u32 i = 0; - - ACPI_FUNCTION_TRACE("acpi_evaluate_reference"); - - if (!list) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Evaluate object. */ - - status = acpi_evaluate(handle, pathname, arguments, &buffer); - if (ACPI_FAILURE(status)) - goto end; - - package = (acpi_object *) buffer.pointer; - - if (!package || (package->type != ACPI_TYPE_PACKAGE) - || (package->package.count == 0)) { - status = AE_BAD_DATA; - acpi_util_eval_error(handle, pathname, status); - goto end; - } - - /* Allocate list - CALLER MUST FREE! */ - list->count = package->package.count; - if (list->count > 10) { - return AE_NO_MEMORY; - } - /* TBD: dynamically allocate */ - /* - list->handles = kmalloc(sizeof(acpi_handle)*(list->count), GFP_KERNEL); - if (!list->handles) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - memset(list->handles, 0, sizeof(acpi_handle)*(list->count)); - */ - - /* Parse package data. */ - - for (i = 0; i < list->count; i++) { - - element = &(package->package.elements[i]); - - if (!element || (element->type != ACPI_TYPE_STRING)) { - status = AE_BAD_DATA; - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid element in package (not a device reference)\n")); - acpi_util_eval_error(handle, pathname, status); - break; - } - - /* Convert reference (e.g. "\_PR_.CPU_") to acpi_handle. */ - - status = acpi_get_handle(handle, element->string.pointer, - &(list->handles[i])); - if (ACPI_FAILURE(status)) { - status = AE_BAD_DATA; - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to resolve device reference [%s]\n", element->string.pointer)); - acpi_util_eval_error(handle, pathname, status); - break; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resolved reference [%s]->[%p]\n", element->string.pointer, list->handles[i])); - } - -end: - if (ACPI_FAILURE(status)) { - list->count = 0; - //kfree(list->handles); - } - - kfree(buffer.pointer); - - return_ACPI_STATUS(status); -} - - diff -Nru a/drivers/acpi/battery.c b/drivers/acpi/battery.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/battery.c Sun Jun 2 18:44:56 2002 @@ -0,0 +1,830 @@ +/* + * acpi_battery.c - ACPI Battery Driver ($Revision: 35 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_BATTERY_COMPONENT +ACPI_MODULE_NAME ("acpi_battery") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + + +#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF + +#define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS" +#define ACPI_BATTERY_FORMAT_BST "NNNN" + +static int acpi_battery_add (struct acpi_device *device); +static int acpi_battery_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_battery_driver = { + name: ACPI_BATTERY_DRIVER_NAME, + class: ACPI_BATTERY_CLASS, + ids: ACPI_BATTERY_HID, + ops: { + add: acpi_battery_add, + remove: acpi_battery_remove, + }, +}; + +struct acpi_battery_status { + acpi_integer state; + acpi_integer present_rate; + acpi_integer remaining_capacity; + acpi_integer present_voltage; +}; + +struct acpi_battery_info { + acpi_integer power_unit; + acpi_integer design_capacity; + acpi_integer last_full_capacity; + acpi_integer battery_technology; + acpi_integer design_voltage; + acpi_integer design_capacity_warning; + acpi_integer design_capacity_low; + acpi_integer battery_capacity_granularity_1; + acpi_integer battery_capacity_granularity_2; + acpi_string model_number; + acpi_string serial_number; + acpi_string battery_type; + acpi_string oem_info; +}; + +struct acpi_battery_flags { + u8 present:1; /* Bay occupied? */ + u8 power_unit:1; /* 0=watts, 1=apms */ + u8 alarm:1; /* _BTP present? */ + u8 reserved:5; +}; + +struct acpi_battery_trips { + unsigned long warning; + unsigned long low; +}; + +struct acpi_battery { + acpi_handle handle; + struct acpi_battery_flags flags; + struct acpi_battery_trips trips; + unsigned long alarm; + struct acpi_battery_info *info; +}; + + +/* -------------------------------------------------------------------------- + Battery Management + -------------------------------------------------------------------------- */ + +static int +acpi_battery_get_info ( + struct acpi_battery *battery, + struct acpi_battery_info **bif) +{ + int result = 0; + acpi_status status = 0; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BIF), + ACPI_BATTERY_FORMAT_BIF}; + acpi_buffer data = {0, NULL}; + acpi_object *package = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_get_info"); + + if (!battery || !bif) + return_VALUE(-EINVAL); + + /* Evalute _BIF */ + + status = acpi_evaluate_object(battery->handle, "_BIF", NULL, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BIF\n")); + return_VALUE(-ENODEV); + } + + package = (acpi_object *) buffer.pointer; + + /* Extract Package Data */ + + status = acpi_extract_package(package, &format, &data); + if (status != AE_BUFFER_OVERFLOW) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n")); + result = -ENODEV; + goto end; + } + + data.pointer = kmalloc(data.length, GFP_KERNEL); + if (!data.pointer) { + result = -ENOMEM; + goto end; + } + memset(data.pointer, 0, data.length); + + status = acpi_extract_package(package, &format, &data); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n")); + kfree(data.pointer); + result = -ENODEV; + goto end; + } + +end: + kfree(buffer.pointer); + + if (!result) + (*bif) = (struct acpi_battery_info *) data.pointer; + + return_VALUE(result); +} + +static int +acpi_battery_get_status ( + struct acpi_battery *battery, + struct acpi_battery_status **bst) +{ + int result = 0; + acpi_status status = 0; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BST), + ACPI_BATTERY_FORMAT_BST}; + acpi_buffer data = {0, NULL}; + acpi_object *package = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_get_status"); + + if (!battery || !bst) + return_VALUE(-EINVAL); + + /* Evalute _BST */ + + status = acpi_evaluate_object(battery->handle, "_BST", NULL, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BST\n")); + return_VALUE(-ENODEV); + } + + package = (acpi_object *) buffer.pointer; + + /* Extract Package Data */ + + status = acpi_extract_package(package, &format, &data); + if (status != AE_BUFFER_OVERFLOW) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n")); + result = -ENODEV; + goto end; + } + + data.pointer = kmalloc(data.length, GFP_KERNEL); + if (!data.pointer) { + result = -ENOMEM; + goto end; + } + memset(data.pointer, 0, data.length); + + status = acpi_extract_package(package, &format, &data); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n")); + kfree(data.pointer); + result = -ENODEV; + goto end; + } + +end: + kfree(buffer.pointer); + + if (!result) + (*bst) = (struct acpi_battery_status *) data.pointer; + + return_VALUE(result); +} + + +static int +acpi_battery_set_alarm ( + struct acpi_battery *battery, + unsigned long alarm) +{ + acpi_status status = 0; + acpi_object arg0 = {ACPI_TYPE_INTEGER}; + acpi_object_list arg_list = {1, &arg0}; + + ACPI_FUNCTION_TRACE("acpi_battery_set_alarm"); + + if (!battery) + return_VALUE(-EINVAL); + + if (!battery->flags.alarm) + return_VALUE(-ENODEV); + + arg0.integer.value = alarm; + + status = acpi_evaluate(battery->handle, "_BTP", &arg_list, NULL); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm)); + + battery->alarm = alarm; + + return_VALUE(0); +} + + +static int +acpi_battery_check ( + struct acpi_battery *battery) +{ + int result = 0; + acpi_status status = AE_OK; + acpi_handle handle = NULL; + struct acpi_device *device = NULL; + struct acpi_battery_info *bif = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_check"); + + if (!battery) + return_VALUE(-EINVAL); + + result = acpi_bus_get_device(battery->handle, &device); + if (result) + return_VALUE(result); + + result = acpi_bus_get_status(device); + if (result) + return_VALUE(result); + + /* Insertion? */ + + if (!battery->flags.present && device->status.battery_present) { + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n")); + + /* Evalute _BIF to get certain static information */ + + result = acpi_battery_get_info(battery, &bif); + if (result) + return_VALUE(result); + + battery->flags.power_unit = bif->power_unit; + battery->trips.warning = bif->design_capacity_warning; + battery->trips.low = bif->design_capacity_low; + kfree(bif); + + /* See if alarms are supported, and if so, set default */ + + status = acpi_get_handle(battery->handle, "_BTP", &handle); + if (ACPI_SUCCESS(status)) { + battery->flags.alarm = 1; + acpi_battery_set_alarm(battery, battery->trips.warning); + } + } + + /* Removal? */ + + else if (battery->flags.present && !device->status.battery_present) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n")); + } + + battery->flags.present = device->status.battery_present; + + return_VALUE(result); +} + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +struct proc_dir_entry *acpi_battery_dir = NULL; + +static int +acpi_battery_read_info ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + int result = 0; + struct acpi_battery *battery = (struct acpi_battery *) data; + struct acpi_battery_info *bif = NULL; + char *units = "?"; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_read_info"); + + if (!battery) + goto end; + + if (battery->flags.present) + p += sprintf(p, "present: yes\n"); + else { + p += sprintf(p, "present: no\n"); + goto end; + } + + /* Battery Info (_BIF) */ + + result = acpi_battery_get_info(battery, &bif); + if (result || !bif) { + p += sprintf(p, "ERROR: Unable to read battery information\n"); + goto end; + } + + units = bif->power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; + + if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "design capacity: unknown\n"); + else + p += sprintf(p, "design capacity: %d %sh\n", + (u32) bif->design_capacity, units); + + if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "last full capacity: unknown\n"); + else + p += sprintf(p, "last full capacity: %d %sh\n", + (u32) bif->last_full_capacity, units); + + switch ((u32) bif->battery_technology) { + case 0: + p += sprintf(p, "battery technology: non-rechargeable\n"); + break; + case 1: + p += sprintf(p, "battery technology: rechargeable\n"); + break; + default: + p += sprintf(p, "battery technology: unknown\n"); + break; + } + + if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "design voltage: unknown\n"); + else + p += sprintf(p, "design voltage: %d mV\n", + (u32) bif->design_voltage); + + p += sprintf(p, "design capacity warning: %d %sh\n", + (u32) bif->design_capacity_warning, units); + p += sprintf(p, "design capacity low: %d %sh\n", + (u32) bif->design_capacity_low, units); + p += sprintf(p, "capacity granularity 1: %d %sh\n", + (u32) bif->battery_capacity_granularity_1, units); + p += sprintf(p, "capacity granularity 2: %d %sh\n", + (u32) bif->battery_capacity_granularity_2, units); + p += sprintf(p, "model number: %s\n", + bif->model_number); + p += sprintf(p, "serial number: %s\n", + bif->serial_number); + p += sprintf(p, "battery type: %s\n", + bif->battery_type); + p += sprintf(p, "OEM info: %s\n", + bif->oem_info); + +end: + kfree(bif); + + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_battery_read_state ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + int result = 0; + struct acpi_battery *battery = (struct acpi_battery *) data; + struct acpi_battery_status *bst = NULL; + char *units = "?"; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_read_state"); + + if (!battery) + goto end; + + if (battery->flags.present) + p += sprintf(p, "present: yes\n"); + else { + p += sprintf(p, "present: no\n"); + goto end; + } + + /* Battery Units */ + + units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; + + /* Battery Status (_BST) */ + + result = acpi_battery_get_status(battery, &bst); + if (result || !bst) { + p += sprintf(p, "ERROR: Unable to read battery status\n"); + goto end; + } + + if (!(bst->state & 0x04)) + p += sprintf(p, "capacity state: ok\n"); + else + p += sprintf(p, "capacity state: critical\n"); + + if ((bst->state & 0x01) && (bst->state & 0x02)) + p += sprintf(p, "charging state: charging/discharging\n"); + else if (bst->state & 0x01) + p += sprintf(p, "charging state: discharging\n"); + else if (bst->state & 0x02) + p += sprintf(p, "charging state: charging\n"); + else + p += sprintf(p, "charging state: unknown\n"); + + if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "present rate: unknown\n"); + else + p += sprintf(p, "present rate: %d %s\n", + (u32) bst->present_rate, units); + + if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "remaining capacity: unknown\n"); + else + p += sprintf(p, "remaining capacity: %d %sh\n", + (u32) bst->remaining_capacity, units); + + if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN) + p += sprintf(p, "present voltage: unknown\n"); + else + p += sprintf(p, "present voltage: %d mV\n", + (u32) bst->present_voltage); + +end: + kfree(bst); + + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_battery_read_alarm ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_battery *battery = (struct acpi_battery *) data; + char *units = "?"; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_read_alarm"); + + if (!battery) + goto end; + + if (!battery->flags.present) { + p += sprintf(p, "present: no\n"); + goto end; + } + + /* Battery Units */ + + units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; + + /* Battery Alarm */ + + p += sprintf(p, "alarm: "); + if (!battery->alarm) + p += sprintf(p, "unsupported\n"); + else + p += sprintf(p, "%d %sh\n", (u32) battery->alarm, units); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_battery_write_alarm ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + struct acpi_battery *battery = (struct acpi_battery *) data; + char alarm_string[12] = {'\0'}; + + ACPI_FUNCTION_TRACE("acpi_battery_write_alarm"); + + if (!battery || (count > sizeof(alarm_string) - 1)) + return_VALUE(-EINVAL); + + if (!battery->flags.present) + return_VALUE(-ENODEV); + + if (copy_from_user(alarm_string, buffer, count)) + return_VALUE(-EFAULT); + + alarm_string[count] = '\0'; + + result = acpi_battery_set_alarm(battery, + simple_strtoul(alarm_string, NULL, 0)); + if (result) + return_VALUE(result); + + return_VALUE(count); +} + + +static int +acpi_battery_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_add_fs"); + + if (!acpi_battery_dir) { + acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir); + if (!acpi_battery_dir) + return_VALUE(-ENODEV); + } + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_battery_dir); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + } + + /* 'info' [R] */ + entry = create_proc_entry(ACPI_BATTERY_FILE_INFO, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BATTERY_FILE_INFO)); + else { + entry->read_proc = acpi_battery_read_info; + entry->data = acpi_driver_data(device); + } + + /* 'status' [R] */ + entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BATTERY_FILE_STATUS)); + else { + entry->read_proc = acpi_battery_read_state; + entry->data = acpi_driver_data(device); + } + + /* 'alarm' [R/W] */ + entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BATTERY_FILE_ALARM)); + else { + entry->read_proc = acpi_battery_read_alarm; + entry->write_proc = acpi_battery_write_alarm; + entry->data = acpi_driver_data(device); + } + + return_VALUE(0); +} + + +static int +acpi_battery_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_battery_remove_fs"); + + if (!acpi_battery_dir) + return_VALUE(-ENODEV); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +static void +acpi_battery_notify ( + acpi_handle handle, + u32 event, + void *data) +{ + struct acpi_battery *battery = (struct acpi_battery *) data; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_notify"); + + if (!battery) + return_VOID; + + if (acpi_bus_get_device(handle, &device)) + return_VOID; + + switch (event) { + case ACPI_BATTERY_NOTIFY_STATUS: + case ACPI_BATTERY_NOTIFY_INFO: + acpi_battery_check(battery); + acpi_bus_generate_event(device, event, battery->flags.present); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return_VOID; +} + + +static int +acpi_battery_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = 0; + struct acpi_battery *battery = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_add"); + + if (!device) + return_VALUE(-EINVAL); + + battery = kmalloc(sizeof(struct acpi_battery), GFP_KERNEL); + if (!battery) + return_VALUE(-ENOMEM); + memset(battery, 0, sizeof(struct acpi_battery)); + + battery->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_BATTERY_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_BATTERY_CLASS); + acpi_driver_data(device) = battery; + + result = acpi_battery_check(battery); + if (result) + goto end; + + result = acpi_battery_add_fs(device); + if (result) + goto end; + + status = acpi_install_notify_handler(battery->handle, + ACPI_DEVICE_NOTIFY, acpi_battery_notify, battery); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing notify handler\n")); + result = -ENODEV; + goto end; + } + + printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", + ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), + device->status.battery_present?"present":"absent"); + +end: + if (result) { + acpi_battery_remove_fs(device); + kfree(battery); + } + + return_VALUE(result); +} + + +static int +acpi_battery_remove ( + struct acpi_device *device, + int type) +{ + acpi_status status = 0; + struct acpi_battery *battery = NULL; + + ACPI_FUNCTION_TRACE("acpi_battery_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + battery = (struct acpi_battery *) acpi_driver_data(device); + + status = acpi_remove_notify_handler(battery->handle, + ACPI_DEVICE_NOTIFY, acpi_battery_notify); + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + + acpi_battery_remove_fs(device); + + kfree(battery); + + return_VALUE(0); +} + + +static int __init +acpi_battery_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_init"); + + result = acpi_bus_register_driver(&acpi_battery_driver); + if (result < 0) { + remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +static void __exit +acpi_battery_exit (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_battery_exit"); + + result = acpi_bus_unregister_driver(&acpi_battery_driver); + if (!result) + remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); + + return_VOID; +} + + +module_init(acpi_battery_init); +module_exit(acpi_battery_exit); diff -Nru a/drivers/acpi/bus.c b/drivers/acpi/bus.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/bus.c Sun Jun 2 18:44:58 2002 @@ -0,0 +1,2195 @@ +/* + * acpi_bus.c - ACPI Bus Driver ($Revision: 77 $) + * + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" +#include "include/acinterp.h" /* for acpi_ex_eisa_id_to_string() */ + + +#define _COMPONENT ACPI_BUS_COMPONENT +ACPI_MODULE_NAME ("acpi_bus") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_BUS_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + +FADT_DESCRIPTOR acpi_fadt; +static u8 acpi_disabled; +struct acpi_device *acpi_root; +struct proc_dir_entry *acpi_root_dir; + +#define STRUCT_TO_INT(s) (*((int*)&s)) + +/* + * POLICY: If *anything* doesn't work, put it on the blacklist. + * If they are critical errors, mark it critical, and abort driver load. + */ +static struct acpi_blacklist_item acpi_blacklist[] __initdata = +{ + /* Portege 7020, BIOS 8.10 */ + {"TOSHIB", "7020CT ", 0x19991112, ACPI_TABLE_DSDT, all_versions, "Implicit Return", 0}, + /* Portege 4030 */ + {"TOSHIB", "4030 ", 0x19991112, ACPI_TABLE_DSDT, all_versions, "Implicit Return", 0}, + /* Portege 310/320, BIOS 7.1 */ + {"TOSHIB", "310 ", 0x19990511, ACPI_TABLE_DSDT, all_versions, "Implicit Return", 0}, + /* Seattle 2, old bios rev. */ + {"INTEL ", "440BX ", 0x00001000, ACPI_TABLE_DSDT, less_than_or_equal, "Field beyond end of region", 0}, + /* ASUS K7M */ + {"ASUS ", "K7M ", 0x00001000, ACPI_TABLE_DSDT, less_than_or_equal, "Field beyond end of region", 0}, + /* Intel 810 Motherboard? */ + {"MNTRAL", "MO81010A", 0x00000012, ACPI_TABLE_DSDT, less_than_or_equal, "Field beyond end of region", 0}, + /* Compaq Presario 711FR */ + {"COMAPQ", "EAGLES", 0x06040000, ACPI_TABLE_DSDT, less_than_or_equal, "SCI issues (C2 disabled)", 0}, + /* Compaq Presario 1700 */ + {"PTLTD ", " DSDT ", 0x06040000, ACPI_TABLE_DSDT, less_than_or_equal, "Multiple problems", 1}, + /* Sony FX120, FX140, FX150? */ + {"SONY ", "U0 ", 0x20010313, ACPI_TABLE_DSDT, less_than_or_equal, "ACPI driver problem", 1}, + /* Compaq Presario 800, Insyde BIOS */ + {"INT440", "SYSFexxx", 0x00001001, ACPI_TABLE_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1}, + /* IBM 600E - _ADR should return 7, but it returns 1 */ + {"IBM ", "TP600E ", 0x00000105, ACPI_TABLE_DSDT, less_than_or_equal, "Incorrect _ADR", 1}, + {""} +}; + + +/* -------------------------------------------------------------------------- + Linux Driver Model (LDM) Support + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_LDM + +static int acpi_device_probe(struct device *dev); +static int acpi_device_remove(struct device *dev, u32 flags); +static int acpi_device_suspend(struct device *dev, u32 state, u32 stage); +static int acpi_device_resume(struct device *dev, u32 stage); + +static struct device_driver acpi_bus_driver = { + probe: acpi_device_probe, + remove: acpi_device_remove, + suspend: acpi_device_suspend, + resume: acpi_device_resume, +}; + + +static int +acpi_device_probe ( + struct device *dev) +{ + ACPI_FUNCTION_TRACE("acpi_device_probe"); + + if (!dev) + return_VALUE(-EINVAL); + + /* TBD */ + + return_VALUE(0); +} + + +static int +acpi_device_remove ( + struct device *dev, + u32 flags) +{ + ACPI_FUNCTION_TRACE("acpi_device_remove"); + + if (!dev) + return_VALUE(-EINVAL); + + /* TBD */ + + return_VALUE(0); +} + + +static int +acpi_device_suspend ( + struct device *dev, + u32 state, + u32 stage) +{ + ACPI_FUNCTION_TRACE("acpi_device_suspend"); + + if (!dev) + return_VALUE(-EINVAL); + + /* TBD */ + + return_VALUE(0); +} + + +static int +acpi_device_resume ( + struct device *dev, + u32 stage) +{ + ACPI_FUNCTION_TRACE("acpi_device_resume"); + + if (!dev) + return_VALUE(-EINVAL); + + /* TBD */ + + return_VALUE(0); +} + +#if 0 /* not used ATM */ +static int +acpi_platform_add ( + struct device *dev) +{ + ACPI_FUNCTION_TRACE("acpi_platform_add"); + + if (!dev) + return -EINVAL; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s (%s) added\n", + dev->name, dev->bus_id)); + + /* TBD */ + + return_VALUE(0); +} + + +static int +acpi_platform_remove ( + struct device *dev) +{ + ACPI_FUNCTION_TRACE("acpi_platform_add"); + + if (!dev) + return -EINVAL; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s (%s) removed\n", + dev->name, dev->bus_id)); + + /* TBD */ + + return_VALUE(0); +} +#endif /* unused */ + + +#endif /*CONFIG_LDM*/ + + +static int +acpi_device_register ( + struct acpi_device *device, + struct acpi_device *parent) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_device_register"); + + if (!device) + return_VALUE(-EINVAL); + +#ifdef CONFIG_LDM + sprintf(device->dev.name, "ACPI device %s:%s", + device->pnp.hardware_id, device->pnp.unique_id); + strncpy(device->dev.bus_id, device->pnp.bus_id, sizeof(acpi_bus_id)); + if (parent) + device->dev.parent = &parent->dev; + device->dev.driver = &acpi_bus_driver; + + result = device_register(&device->dev); +#endif /*CONFIG_LDM*/ + + return_VALUE(result); +} + + +static int +acpi_device_unregister ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_device_unregister"); + + if (!device) + return_VALUE(-EINVAL); + +#ifdef CONFIG_LDM + put_device(&device->dev); +#endif /*CONFIG_LDM*/ + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Device Management + -------------------------------------------------------------------------- */ + +static void +acpi_bus_data_handler ( + acpi_handle handle, + u32 function, + void *context) +{ + ACPI_FUNCTION_TRACE("acpi_bus_data_handler"); + + /* TBD */ + + return_VOID; +} + + +int +acpi_bus_get_device ( + acpi_handle handle, + struct acpi_device **device) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_bus_get_device"); + + if (!device) + return_VALUE(-EINVAL); + + /* TBD: Support fixed-feature devices */ + + status = acpi_get_data(handle, acpi_bus_data_handler, (void**) device); + if (ACPI_FAILURE(status) || !*device) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error getting context for object [%p]\n", + handle)); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + +int +acpi_bus_get_status ( + struct acpi_device *device) +{ + acpi_status status = AE_OK; + unsigned long sta = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_get_status"); + + if (!device) + return_VALUE(-EINVAL); + + /* + * Evaluate _STA if present. + */ + if (device->flags.dynamic_status) { + status = acpi_evaluate_integer(device->handle, "_STA", NULL, &sta); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + STRUCT_TO_INT(device->status) = (int) sta; + } + + /* + * Otherwise we assume the status of our parent (unless we don't + * have one, in which case status is implied). + */ + else if (device->parent) + device->status = device->parent->status; + else + STRUCT_TO_INT(device->status) = 0x0F; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", + device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status))); + + return_VALUE(0); +} + + +/* +static int +acpi_bus_create_device_fs (struct device *device) +{ + ACPI_FUNCTION_TRACE("acpi_bus_create_device_fs"); + + if (!device) + return_VALUE(-EINVAL); + + if (device->dir.entry) + return_VALUE(-EEXIST); + + if (!device->parent) + device->dir.entry = proc_mkdir(device->pnp.bus_id, NULL); + else + device->dir.entry = proc_mkdir(device->pnp.bus_id, + device->parent->fs.entry); + + if (!device->dir.entry) { + printk(KERN_ERR PREFIX "Unable to create fs entry '%s'\n", + device->pnp.bus_id); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +static int +acpi_bus_remove_device_fs (struct device *device) +{ + ACPI_FUNCTION_TRACE("acpi_bus_create_device_fs"); + + if (!device) + return_VALUE(-EINVAL); + + if (!device->dir.entry) + return_VALUE(-ENODEV); + + if (!device->parent) + remove_proc_entry(device->pnp_bus_id, NULL); + else + remove_proc_entry(device->pnp.bus_id, device->parent->fs.entry); + + device->dir.entry = NULL; + + return_VALUE(0); +} +*/ + + +/* -------------------------------------------------------------------------- + Power Management + -------------------------------------------------------------------------- */ + +int +acpi_bus_get_power ( + acpi_handle handle, + int *state) +{ + int result = 0; + acpi_status status = 0; + struct acpi_device *device = NULL; + unsigned long psc = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_get_power"); + + result = acpi_bus_get_device(handle, &device); + if (result) + return_VALUE(result); + + *state = ACPI_STATE_UNKNOWN; + + if (!device->flags.power_manageable) { + /* TBD: Non-recursive algorithm for walking up hierarchy */ + if (device->parent) + *state = device->parent->power.state; + else + *state = ACPI_STATE_D0; + } + else { + /* + * Get the device's power state either directly (via _PSC) or + * indirectly (via power resources). + */ + if (device->power.flags.explicit_get) { + status = acpi_evaluate_integer(device->handle, "_PSC", + NULL, &psc); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + device->power.state = (int) psc; + } + else if (device->power.flags.power_resources) { + result = acpi_power_get_inferred_state(device); + if (result) + return_VALUE(result); + } + + *state = device->power.state; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", + device->pnp.bus_id, device->power.state)); + + return_VALUE(0); +} + + +int +acpi_bus_set_power ( + acpi_handle handle, + int state) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_device *device = NULL; + char object_name[5] = {'_','P','S','0'+state,'\0'}; + + ACPI_FUNCTION_TRACE("acpi_bus_set_power"); + + result = acpi_bus_get_device(handle, &device); + if (result) + return_VALUE(result); + + if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) + return_VALUE(-EINVAL); + + /* Make sure this is a valid target state */ + + if (!device->flags.power_manageable) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device is not power manageable\n")); + return_VALUE(-ENODEV); + } + if (state == device->power.state) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state)); + return_VALUE(0); + } + if (!device->power.states[state].flags.valid) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n", state)); + return_VALUE(-ENODEV); + } + if (device->parent && (state < device->parent->power.state)) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Cannot set device to a higher-powered state than parent\n")); + return_VALUE(-ENODEV); + } + + /* + * Transition Power + * ---------------- + * On transitions to a high-powered state we first apply power (via + * power resources) then evalute _PSx. Conversly for transitions to + * a lower-powered state. + */ + if (state < device->power.state) { + if (device->power.flags.power_resources) { + result = acpi_power_transition(device, state); + if (result) + goto end; + } + if (device->power.states[state].flags.explicit_set) { + status = acpi_evaluate_object(device->handle, + object_name, NULL, NULL); + if (ACPI_FAILURE(status)) { + result = -ENODEV; + goto end; + } + } + } + else { + if (device->power.states[state].flags.explicit_set) { + status = acpi_evaluate_object(device->handle, + object_name, NULL, NULL); + if (ACPI_FAILURE(status)) { + result = -ENODEV; + goto end; + } + } + if (device->power.flags.power_resources) { + result = acpi_power_transition(device, state); + if (result) + goto end; + } + } + +end: + if (result) + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error transitioning device [%s] to D%d\n", + device->pnp.bus_id, state)); + else + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] transitioned to D%d\n", + device->pnp.bus_id, state)); + + return_VALUE(result); +} + + +static int +acpi_bus_get_power_flags ( + struct acpi_device *device) +{ + acpi_status status = 0; + acpi_handle handle = 0; + u32 i = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_get_power_flags"); + + if (!device) + return -ENODEV; + + /* + * Power Management Flags + */ + status = acpi_get_handle(device->handle, "_PSC", &handle); + if (ACPI_SUCCESS(status)) + device->power.flags.explicit_get = 1; + status = acpi_get_handle(device->handle, "_IRC", &handle); + if (ACPI_SUCCESS(status)) + device->power.flags.inrush_current = 1; + status = acpi_get_handle(device->handle, "_PRW", &handle); + if (ACPI_SUCCESS(status)) + device->power.flags.wake_capable = 1; + + /* + * Enumerate supported power management states + */ + for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) { + struct acpi_device_power_state *ps = &device->power.states[i]; + char object_name[5] = {'_','P','R','0'+i,'\0'}; + + /* Evaluate "_PRx" to se if power resources are referenced */ + acpi_evaluate_reference(device->handle, object_name, NULL, + &ps->resources); + if (ps->resources.count) { + device->power.flags.power_resources = 1; + ps->flags.valid = 1; + } + + /* Evaluate "_PSx" to see if we can do explicit sets */ + object_name[2] = 'S'; + status = acpi_get_handle(device->handle, object_name, &handle); + if (ACPI_SUCCESS(status)) { + ps->flags.explicit_set = 1; + ps->flags.valid = 1; + } + + /* State is valid if we have some power control */ + if (ps->resources.count || ps->flags.explicit_set) + ps->flags.valid = 1; + + ps->power = -1; /* Unknown - driver assigned */ + ps->latency = -1; /* Unknown - driver assigned */ + } + + /* Set defaults for D0 and D3 states (always valid) */ + device->power.states[ACPI_STATE_D0].flags.valid = 1; + device->power.states[ACPI_STATE_D0].power = 100; + device->power.states[ACPI_STATE_D3].flags.valid = 1; + device->power.states[ACPI_STATE_D3].power = 0; + + /* + * System Power States + * ------------------- + */ + /* TBD: S1-S4 power state support and resource requirements. */ + /* + for (i=ACPI_STATE_S1; ihandle, name, NULL, + &state); + if (ACPI_FAILURE(status)) + continue; + } + */ + + /* TBD: System wake support and resource requirements. */ + + device->power.state = ACPI_STATE_UNKNOWN; + + return 0; +} + + +/* -------------------------------------------------------------------------- + Performance Management + -------------------------------------------------------------------------- */ + +static int +acpi_bus_get_perf_flags ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_bus_get_perf_flags"); + + if (!device) + return -ENODEV; + + device->performance.state = ACPI_STATE_UNKNOWN; + + return 0; +} + + +/* -------------------------------------------------------------------------- + Event Management + -------------------------------------------------------------------------- */ + +static spinlock_t acpi_bus_event_lock = SPIN_LOCK_UNLOCKED; + +LIST_HEAD(acpi_bus_event_list); +DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue); + +extern int event_is_open; + +int +acpi_bus_generate_event ( + struct acpi_device *device, + u8 type, + int data) +{ + struct acpi_bus_event *event = NULL; + u32 flags = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_generate_event"); + + if (!device) + return_VALUE(-EINVAL); + + /* drop event on the floor if no one's listening */ + if (!event_is_open) + return_VALUE(0); + + event = kmalloc(sizeof(struct acpi_bus_event), GFP_KERNEL); + if (!event) + return_VALUE(-ENOMEM); + + sprintf(event->device_class, "%s", device->pnp.device_class); + sprintf(event->bus_id, "%s", device->pnp.bus_id); + event->type = type; + event->data = data; + + spin_lock_irqsave(&acpi_bus_event_lock, flags); + list_add_tail(&event->node, &acpi_bus_event_list); + spin_unlock_irqrestore(&acpi_bus_event_lock, flags); + + wake_up_interruptible(&acpi_bus_event_queue); + + return_VALUE(0); +} + +int +acpi_bus_receive_event ( + struct acpi_bus_event *event) +{ + u32 flags = 0; + struct acpi_bus_event *entry = NULL; + + DECLARE_WAITQUEUE(wait, current); + + ACPI_FUNCTION_TRACE("acpi_bus_receive_event"); + + if (!event) + return -EINVAL; + + if (list_empty(&acpi_bus_event_list)) { + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&acpi_bus_event_queue, &wait); + + if (list_empty(&acpi_bus_event_list)) + schedule(); + + remove_wait_queue(&acpi_bus_event_queue, &wait); + set_current_state(TASK_RUNNING); + + if (signal_pending(current)) + return_VALUE(-ERESTARTSYS); + } + + spin_lock_irqsave(&acpi_bus_event_lock, flags); + entry = list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node); + if (entry) + list_del(&entry->node); + spin_unlock_irqrestore(&acpi_bus_event_lock, flags); + + if (!entry) + return_VALUE(-ENODEV); + + memcpy(event, entry, sizeof(struct acpi_bus_event)); + + kfree(entry); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Namespace Management + -------------------------------------------------------------------------- */ + +#define WALK_UP 0 +#define WALK_DOWN 1 + +typedef int (*acpi_bus_walk_callback)(struct acpi_device*, int, void*); + +#define HAS_CHILDREN(d) ((d)->children.next != &((d)->children)) +#define HAS_SIBLINGS(d) (((d)->parent) && ((d)->node.next != &(d)->parent->children)) +#define NODE_TO_DEVICE(n) (list_entry(n, struct acpi_device, node)) + + +/** + * acpi_bus_walk + * ------------- + * Used to walk the ACPI Bus's device namespace. Can walk down (depth-first) + * or up. Able to parse starting at any node in the namespace. Note that a + * callback return value of -ELOOP will terminate the walk. + * + * @start: starting point + * callback: function to call for every device encountered while parsing + * direction: direction to parse (up or down) + * @data: context for this search operation + */ +static int +acpi_bus_walk ( + struct acpi_device *start, + acpi_bus_walk_callback callback, + int direction, + void *data) +{ + int result = 0; + int level = 0; + struct acpi_device *device = NULL; + + if (!start || !callback) + return -EINVAL; + + device = start; + + /* + * Parse Namespace + * --------------- + * Parse a given subtree (specified by start) in the given direction. + * Walking 'up' simply means that we execute the callback on leaf + * devices prior to their parents (useful for things like removing + * or powering down a subtree). + */ + + while (device) { + + if (direction == WALK_DOWN) + if (-ELOOP == callback(device, level, data)) + break; + + /* Depth First */ + + if (HAS_CHILDREN(device)) { + device = NODE_TO_DEVICE(device->children.next); + ++level; + continue; + } + + if (direction == WALK_UP) + if (-ELOOP == callback(device, level, data)) + break; + + /* Now Breadth */ + + if (HAS_SIBLINGS(device)) { + device = NODE_TO_DEVICE(device->node.next); + continue; + } + + /* Scope Exhausted - Find Next */ + + while ((device = device->parent)) { + --level; + if (HAS_SIBLINGS(device)) { + device = NODE_TO_DEVICE(device->node.next); + break; + } + } + } + + if ((direction == WALK_UP) && (result == 0)) + callback(start, level, data); + + return result; +} + + +/* -------------------------------------------------------------------------- + Notification Handling + -------------------------------------------------------------------------- */ + +static int +acpi_bus_check_device ( + struct acpi_device *device, + int *status_changed) +{ + acpi_status status = 0; + struct acpi_device_status old_status; + + ACPI_FUNCTION_TRACE("acpi_bus_check_device"); + + if (!device) + return_VALUE(-EINVAL); + + if (status_changed) + *status_changed = 0; + + old_status = device->status; + + /* + * Make sure this device's parent is present before we go about + * messing with the device. + */ + if (device->parent && !device->parent->status.present) { + device->status = device->parent->status; + if (STRUCT_TO_INT(old_status) != STRUCT_TO_INT(device->status)) { + if (status_changed) + *status_changed = 1; + } + return_VALUE(0); + } + + status = acpi_bus_get_status(device); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) + return_VALUE(0); + + if (status_changed) + *status_changed = 1; + + /* + * Device Insertion/Removal + */ + if ((device->status.present) && !(old_status.present)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n")); + /* TBD: Handle device insertion */ + } + else if (!(device->status.present) && (old_status.present)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); + /* TBD: Handle device removal */ + } + + return_VALUE(0); +} + + +static int +acpi_bus_check_scope ( + struct acpi_device *device) +{ + int result = 0; + int status_changed = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_check_scope"); + + if (!device) + return_VALUE(-EINVAL); + + /* Status Change? */ + result = acpi_bus_check_device(device, &status_changed); + if (result) + return_VALUE(result); + + if (!status_changed) + return_VALUE(0); + + /* + * TBD: Enumerate child devices within this device's scope and + * run acpi_bus_check_device()'s on them. + */ + + return_VALUE(0); +} + + +/** + * acpi_bus_notify + * --------------- + * Callback for all 'system-level' device notifications (values 0x00-0x7F). + */ +static void +acpi_bus_notify ( + acpi_handle handle, + u32 type, + void *data) +{ + int result = 0; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_bus_notify"); + + if (acpi_bus_get_device(handle, &device)) + return_VOID; + + switch (type) { + + case ACPI_NOTIFY_BUS_CHECK: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS CHECK notification for device [%s]\n", + device->pnp.bus_id)); + result = acpi_bus_check_scope(device); + /* + * TBD: We'll need to outsource certain events to non-ACPI + * drivers via the device manager (device.c). + */ + break; + + case ACPI_NOTIFY_DEVICE_CHECK: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK notification for device [%s]\n", + device->pnp.bus_id)); + result = acpi_bus_check_device(device, NULL); + /* + * TBD: We'll need to outsource certain events to non-ACPI + * drivers via the device manager (device.c). + */ + break; + + case ACPI_NOTIFY_DEVICE_WAKE: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE WAKE notification for device [%s]\n", + device->pnp.bus_id)); + /* TBD */ + break; + + case ACPI_NOTIFY_EJECT_REQUEST: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received EJECT REQUEST notification for device [%s]\n", + device->pnp.bus_id)); + /* TBD */ + break; + + case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK LIGHT notification for device [%s]\n", + device->pnp.bus_id)); + /* TBD: Exactly what does 'light' mean? */ + break; + + case ACPI_NOTIFY_FREQUENCY_MISMATCH: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received FREQUENCY MISMATCH notification for device [%s]\n", + device->pnp.bus_id)); + /* TBD */ + break; + + case ACPI_NOTIFY_BUS_MODE_MISMATCH: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS MODE MISMATCH notification for device [%s]\n", + device->pnp.bus_id)); + /* TBD */ + break; + + case ACPI_NOTIFY_POWER_FAULT: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received POWER FAULT notification for device [%s]\n", + device->pnp.bus_id)); + /* TBD */ + break; + + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received unknown/unsupported notification [%08x]\n", + type)); + break; + } + + return_VOID; +} + + +/* -------------------------------------------------------------------------- + Driver Management + -------------------------------------------------------------------------- */ + +static LIST_HEAD(acpi_bus_drivers); +static DECLARE_MUTEX(acpi_bus_drivers_lock); + + +/** + * acpi_bus_match + * -------------- + * Checks the device's hardware (_HID) or compatible (_CID) ids to see if it + * matches the specified driver's criteria. + */ +static int +acpi_bus_match ( + struct acpi_device *device, + struct acpi_driver *driver) +{ + + if (!device || !driver) + return -EINVAL; + + if (device->flags.hardware_id) { + if (strstr(driver->ids, device->pnp.hardware_id)) + return 0; + } + + if (device->flags.compatible_ids) { + acpi_status status = AE_OK; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_object *object = NULL; + char cid[256]; + + memset(cid, 0, sizeof(cid)); + + status = acpi_evaluate_object(device->handle, "_CID", NULL, + &buffer); + if (ACPI_FAILURE(status) || !buffer.pointer) + return -ENOENT; + + object = (acpi_object *) buffer.pointer; + + switch (object->type) { + case ACPI_TYPE_INTEGER: + acpi_ex_eisa_id_to_string((u32) object->integer.value, + cid); + break; + case ACPI_TYPE_STRING: + strncpy(cid, object->string.pointer, sizeof(cid) - 1); + break; + case ACPI_TYPE_PACKAGE: + /* TBD: Support CID packages */ + break; + } + + if (!cid[0]) + return -ENOENT; + + if (strstr(driver->ids, cid)) + return 0; + } + + return -ENOENT; +} + + +/** + * acpi_bus_driver_init + * -------------------- + * Used to initialize a device via its device driver. Called whenever a + * driver is bound to a device. Invokes the driver's add() and start() ops. + */ +static int +acpi_bus_driver_init ( + struct acpi_device *device, + struct acpi_driver *driver) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_driver_init"); + + if (!device || !driver) + return_VALUE(-EINVAL); + + if (!driver->ops.add) + return_VALUE(-ENOSYS); + + result = driver->ops.add(device); + if (result) { + device->driver = NULL; + acpi_driver_data(device) = NULL; + return_VALUE(result); + } + + /* + * TBD - Configuration Management: Assign resources to device based + * upon possible configuration and currently allocated resources. + */ + + if (driver->ops.start) { + result = driver->ops.start(device); + if (result && driver->ops.remove) + driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); + return_VALUE(result); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n")); + +#ifdef CONFIG_LDM + /* + * Update the device information (in the global device hierarchy) now + * that there's a driver bound to it. + */ + strncpy(device->dev.name, device->pnp.device_name, + sizeof(device->dev.name)); +#endif + + if (driver->ops.scan) { + driver->ops.scan(device); + } + + return_VALUE(0); +} + + +/** + * acpi_bus_attach + * ------------- + * Callback for acpi_bus_walk() used to find devices that match a specific + * driver's criteria and then attach the driver. + */ +static int +acpi_bus_attach ( + struct acpi_device *device, + int level, + void *data) +{ + int result = 0; + struct acpi_driver *driver = NULL; + + ACPI_FUNCTION_TRACE("acpi_bus_attach"); + + if (!device || !data) + return_VALUE(-EINVAL); + + driver = (struct acpi_driver *) data; + + if (device->driver) + return_VALUE(-EEXIST); + + if (!device->status.present) + return_VALUE(-ENODEV); + + result = acpi_bus_match(device, driver); + if (result) + return_VALUE(result); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", + driver->name, device->pnp.bus_id)); + + result = acpi_bus_driver_init(device, driver); + if (result) + return_VALUE(result); + + down(&acpi_bus_drivers_lock); + ++driver->references; + up(&acpi_bus_drivers_lock); + + return_VALUE(0); +} + + +/** + * acpi_bus_unattach + * ----------------- + * Callback for acpi_bus_walk() used to find devices that match a specific + * driver's criteria and unattach the driver. + */ +static int +acpi_bus_unattach ( + struct acpi_device *device, + int level, + void *data) +{ + int result = 0; + struct acpi_driver *driver = (struct acpi_driver *) data; + + ACPI_FUNCTION_TRACE("acpi_bus_unattach"); + + if (!device || !driver) + return_VALUE(-EINVAL); + + if (device->driver != driver) + return_VALUE(-ENOENT); + + if (!driver->ops.remove) + return_VALUE(-ENOSYS); + + result = driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); + if (result) + return_VALUE(result); + + device->driver = NULL; + acpi_driver_data(device) = NULL; + + down(&acpi_bus_drivers_lock); + driver->references--; + up(&acpi_bus_drivers_lock); + + return_VALUE(0); +} + + +/** + * acpi_bus_find_driver + * -------------------- + * Parses the list of registered drivers looking for a driver applicable for + * the specified device. + */ +static int +acpi_bus_find_driver ( + struct acpi_device *device) +{ + int result = -ENODEV; + struct list_head *entry = NULL; + struct acpi_driver *driver = NULL; + + ACPI_FUNCTION_TRACE("acpi_bus_find_driver"); + + if (!device || device->driver) + return_VALUE(-EINVAL); + + down(&acpi_bus_drivers_lock); + + list_for_each(entry, &acpi_bus_drivers) { + + driver = list_entry(entry, struct acpi_driver, node); + + if (acpi_bus_match(device, driver)) + continue; + + result = acpi_bus_driver_init(device, driver); + if (!result) + ++driver->references; + + break; + } + + up(&acpi_bus_drivers_lock); + + return_VALUE(result); +} + + +/** + * acpi_bus_register_driver + * ------------------------ + * Registers a driver with the ACPI bus. Searches the namespace for all + * devices that match the driver's criteria and binds. + */ +int +acpi_bus_register_driver ( + struct acpi_driver *driver) +{ + ACPI_FUNCTION_TRACE("acpi_bus_register_driver"); + + if (!driver) + return_VALUE(-EINVAL); + + down(&acpi_bus_drivers_lock); + list_add_tail(&driver->node, &acpi_bus_drivers); + up(&acpi_bus_drivers_lock); + + acpi_bus_walk(acpi_root, acpi_bus_attach, + WALK_DOWN, driver); + + return_VALUE(driver->references); +} + + +/** + * acpi_bus_unregister_driver + * -------------------------- + * Unregisters a driver with the ACPI bus. Searches the namespace for all + * devices that match the driver's criteria and unbinds. + */ +int +acpi_bus_unregister_driver ( + struct acpi_driver *driver) +{ + ACPI_FUNCTION_TRACE("acpi_bus_unregister_driver"); + + if (!driver) + return_VALUE(-EINVAL); + + acpi_bus_walk(acpi_root, acpi_bus_unattach, WALK_UP, driver); + + if (driver->references) + return_VALUE(driver->references); + + down(&acpi_bus_drivers_lock); + list_del(&driver->node); + up(&acpi_bus_drivers_lock); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Device Enumeration + -------------------------------------------------------------------------- */ + +static int +acpi_bus_get_flags ( + struct acpi_device *device) +{ + acpi_status status = AE_OK; + acpi_handle temp = NULL; + + ACPI_FUNCTION_TRACE("acpi_bus_get_flags"); + + /* Presence of _STA indicates 'dynamic_status' */ + status = acpi_get_handle(device->handle, "_STA", &temp); + if (ACPI_SUCCESS(status)) + device->flags.dynamic_status = 1; + + /* Presence of _CID indicates 'compatible_ids' */ + status = acpi_get_handle(device->handle, "_CID", &temp); + if (ACPI_SUCCESS(status)) + device->flags.compatible_ids = 1; + + /* Presence of _RMV indicates 'removable' */ + status = acpi_get_handle(device->handle, "_RMV", &temp); + if (ACPI_SUCCESS(status)) + device->flags.removable = 1; + + /* Presence of _EJD|_EJ0 indicates 'ejectable' */ + status = acpi_get_handle(device->handle, "_EJD", &temp); + if (ACPI_SUCCESS(status)) + device->flags.ejectable = 1; + else { + status = acpi_get_handle(device->handle, "_EJ0", &temp); + if (ACPI_SUCCESS(status)) + device->flags.ejectable = 1; + } + + /* Presence of _LCK indicates 'lockable' */ + status = acpi_get_handle(device->handle, "_LCK", &temp); + if (ACPI_SUCCESS(status)) + device->flags.lockable = 1; + + /* Presence of _PS0|_PR0 indicates 'power manageable' */ + status = acpi_get_handle(device->handle, "_PS0", &temp); + if (ACPI_FAILURE(status)) + status = acpi_get_handle(device->handle, "_PR0", &temp); + if (ACPI_SUCCESS(status)) + device->flags.power_manageable = 1; + + /* TBD: Peformance management */ + + return_VALUE(0); +} + + +static int +acpi_bus_add ( + struct acpi_device **child, + struct acpi_device *parent, + acpi_handle handle, + int type) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_device *device = NULL; + char bus_id[5] = {'?',0}; + acpi_buffer buffer = {sizeof(bus_id), bus_id}; + acpi_device_info info; + char *hid = NULL; + char *uid = NULL; + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_add"); + + if (!child) + return_VALUE(-EINVAL); + + device = kmalloc(sizeof(struct acpi_device), GFP_KERNEL); + if (!device) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Memory allocation error\n")); + return_VALUE(-ENOMEM); + } + memset(device, 0, sizeof(struct acpi_device)); + + device->handle = handle; + device->parent = parent; + + memset(&info, 0, sizeof(acpi_device_info)); + + /* + * Bus ID + * ------ + * The device's Bus ID is simply the object name. + * TBD: Shouldn't this value be unique (within the ACPI namespace)? + */ + switch (type) { + case ACPI_BUS_TYPE_SYSTEM: + sprintf(device->pnp.bus_id, "%s", "ACPI"); + break; + case ACPI_BUS_TYPE_POWER_BUTTON: + sprintf(device->pnp.bus_id, "%s", "PWRF"); + break; + case ACPI_BUS_TYPE_SLEEP_BUTTON: + sprintf(device->pnp.bus_id, "%s", "SLPF"); + break; + default: + acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer); + /* Clean up trailing underscores (if any) */ + for (i = 3; i > 1; i--) { + if (bus_id[i] == '_') + bus_id[i] = '\0'; + else + break; + } + sprintf(device->pnp.bus_id, "%s", bus_id); + break; + } + + /* + * Flags + * ----- + * Get prior to calling acpi_bus_get_status() so we know whether + * or not _STA is present. Note that we only look for object + * handles -- cannot evaluate objects until we know the device is + * present and properly initialized. + */ + result = acpi_bus_get_flags(device); + if (result) + goto end; + + /* + * Status + * ------ + * See if the device is present. We always assume that non-Device() + * objects (e.g. thermal zones, power resources, processors, etc.) are + * present, functioning, etc. (at least when parent object is present). + * Note that _STA has a different meaning for some objects (e.g. + * power resources) so we need to be careful how we use it. + */ + switch (type) { + case ACPI_BUS_TYPE_DEVICE: + result = acpi_bus_get_status(device); + if (result) + goto end; + break; + default: + STRUCT_TO_INT(device->status) = 0x0F; + break; + } + if (!device->status.present) { + result = -ENOENT; + goto end; + } + + /* + * Initialize Device + * ----------------- + * TBD: Synch with Core's enumeration/initialization process. + */ + + /* + * Hardware ID, Unique ID, & Bus Address + * ------------------------------------- + */ + switch (type) { + case ACPI_BUS_TYPE_DEVICE: + status = acpi_get_object_info(handle, &info); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error reading device info\n")); + result = -ENODEV; + goto end; + } + /* Clean up info strings (not NULL terminated) */ + info.hardware_id[sizeof(info.hardware_id)-1] = '\0'; + info.unique_id[sizeof(info.unique_id)-1] = '\0'; + if (info.valid & ACPI_VALID_HID) + hid = info.hardware_id; + if (info.valid & ACPI_VALID_UID) + uid = info.unique_id; + if (info.valid & ACPI_VALID_ADR) { + device->pnp.bus_address = info.address; + device->flags.bus_address = 1; + } + break; + case ACPI_BUS_TYPE_POWER: + hid = ACPI_POWER_HID; + break; + case ACPI_BUS_TYPE_PROCESSOR: + hid = ACPI_PROCESSOR_HID; + break; + case ACPI_BUS_TYPE_SYSTEM: + hid = ACPI_SYSTEM_HID; + break; + case ACPI_BUS_TYPE_THERMAL: + hid = ACPI_THERMAL_HID; + break; + case ACPI_BUS_TYPE_POWER_BUTTON: + hid = ACPI_BUTTON_HID_POWERF; + break; + case ACPI_BUS_TYPE_SLEEP_BUTTON: + hid = ACPI_BUTTON_HID_SLEEPF; + break; + } + + /* + * \_SB + * ---- + * Fix for the system root bus device -- the only root-level device. + */ + if ((parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) { + hid = ACPI_BUS_HID; + sprintf(device->pnp.device_name, "%s", ACPI_BUS_DEVICE_NAME); + sprintf(device->pnp.device_class, "%s", ACPI_BUS_CLASS); + } + + if (hid) { + sprintf(device->pnp.hardware_id, "%s", hid); + device->flags.hardware_id = 1; + } + if (uid) { + sprintf(device->pnp.unique_id, "%s", uid); + device->flags.unique_id = 1; + } + + /* + * Power Management + * ---------------- + */ + if (device->flags.power_manageable) { + result = acpi_bus_get_power_flags(device); + if (result) + goto end; + } + + /* + * Performance Management + * ---------------------- + */ + if (device->flags.performance_manageable) { + result = acpi_bus_get_perf_flags(device); + if (result) + goto end; + } + + /* + * Context + * ------- + * Attach this 'struct acpi_device' to the ACPI object. This makes + * resolutions from handle->device very efficient. Note that we need + * to be careful with fixed-feature devices as they all attach to the + * root object. + */ + switch (type) { + case ACPI_BUS_TYPE_POWER_BUTTON: + case ACPI_BUS_TYPE_SLEEP_BUTTON: + break; + default: + status = acpi_attach_data(device->handle, + acpi_bus_data_handler, device); + break; + } + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error attaching device data\n")); + result = -ENODEV; + goto end; + } + + /* + * Linkage + * ------- + * Link this device to its parent and siblings. + */ + INIT_LIST_HEAD(&device->children); + if (!device->parent) + INIT_LIST_HEAD(&device->node); + else + list_add_tail(&device->node, &device->parent->children); + +#ifdef CONFIG_ACPI_DEBUG + { + char *type_string = NULL; + char name[80] = {'?','\0'}; + acpi_buffer buffer = {sizeof(name), name}; + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + + switch (type) { + case ACPI_BUS_TYPE_DEVICE: + type_string = "Device"; + break; + case ACPI_BUS_TYPE_POWER: + type_string = "Power Resource"; + break; + case ACPI_BUS_TYPE_PROCESSOR: + type_string = "Processor"; + break; + case ACPI_BUS_TYPE_SYSTEM: + type_string = "System"; + break; + case ACPI_BUS_TYPE_THERMAL: + type_string = "Thermal Zone"; + break; + case ACPI_BUS_TYPE_POWER_BUTTON: + type_string = "Power Button"; + sprintf(name, "PWRB"); + break; + case ACPI_BUS_TYPE_SLEEP_BUTTON: + type_string = "Sleep Button"; + sprintf(name, "SLPB"); + break; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s %s [%p]\n", + type_string, name, handle)); + } +#endif /*CONFIG_ACPI_DEBUG*/ + + /* + * Global Device Hierarchy: + * ------------------------ + * Register this device with the global device hierarchy. + */ + acpi_device_register(device, parent); + + /* + * Bind _ADR-Based Devices + * ----------------------- + * If there's a a bus address (_ADR) then we utilize the parent's + * 'bind' function (if exists) to bind the ACPI- and natively- + * enumerated device representations. + */ + if (device->flags.bus_address) { + if (device->parent && device->parent->ops.bind) + device->parent->ops.bind(device); + } + + /* + * Locate & Attach Driver + * ---------------------- + * If there's a hardware id (_HID) or compatible ids (_CID) we check + * to see if there's a driver installed for this kind of device. Note + * that drivers can install before or after a device in enumerated. + * + * TBD: Assumes LDM provides driver hot-plug capability. + */ + if (device->flags.hardware_id || device->flags.compatible_ids) + acpi_bus_find_driver(device); + +end: + if (result) { + kfree(device); + return_VALUE(result); + } + + *child = device; + + return_VALUE(0); +} + + +static int +acpi_bus_remove ( + struct acpi_device *device, + int type) +{ + ACPI_FUNCTION_TRACE("acpi_bus_remove"); + + if (!device) + return_VALUE(-ENODEV); + + acpi_device_unregister(device); + + kfree(device); + + return_VALUE(0); +} + + +int +acpi_bus_scan ( + struct acpi_device *start) +{ + acpi_status status = AE_OK; + struct acpi_device *parent = NULL; + struct acpi_device *child = NULL; + acpi_handle phandle = 0; + acpi_handle chandle = 0; + acpi_object_type type = 0; + u32 level = 1; + + ACPI_FUNCTION_TRACE("acpi_bus_scan"); + + if (!start) + return_VALUE(-EINVAL); + + parent = start; + phandle = start->handle; + + /* + * Parse through the ACPI namespace, identify all 'devices', and + * create a new 'struct acpi_device' for each. + */ + while ((level > 0) && parent) { + + status = acpi_get_next_object(ACPI_TYPE_ANY, phandle, + chandle, &chandle); + + /* + * If this scope is exhausted then move our way back up. + */ + if (ACPI_FAILURE(status)) { + level--; + chandle = phandle; + acpi_get_parent(phandle, &phandle); + if (parent->parent) + parent = parent->parent; + continue; + } + + status = acpi_get_type(chandle, &type); + if (ACPI_FAILURE(status)) + continue; + + /* + * If this is a scope object then parse it (depth-first). + */ + if (type == ACPI_TYPE_ANY) { + /* Hack to get around scope identity problem */ + status = acpi_get_next_object(ACPI_TYPE_ANY, chandle, 0, NULL); + if (ACPI_SUCCESS(status)) { + level++; + phandle = chandle; + chandle = 0; + } + continue; + } + + /* + * We're only interested in objects that we consider 'devices'. + */ + switch (type) { + case ACPI_TYPE_DEVICE: + type = ACPI_BUS_TYPE_DEVICE; + break; + case ACPI_TYPE_PROCESSOR: + type = ACPI_BUS_TYPE_PROCESSOR; + break; + case ACPI_TYPE_THERMAL: + type = ACPI_BUS_TYPE_THERMAL; + break; + case ACPI_TYPE_POWER: + type = ACPI_BUS_TYPE_POWER; + break; + default: + continue; + } + + status = acpi_bus_add(&child, parent, chandle, type); + if (ACPI_FAILURE(status)) + continue; + + /* + * If the device is present, enabled, and functioning then + * parse its scope (depth-first). Note that we need to + * represent absent devices to facilitate PnP notifications + * -- but only the subtree head (not all of its children, + * which will be enumerated when the parent is inserted). + * + * TBD: Need notifications and other detection mechanisms + * in place before we can fully implement this. + */ + if (child->status.present) { + status = acpi_get_next_object(ACPI_TYPE_ANY, chandle, + 0, NULL); + if (ACPI_SUCCESS(status)) { + level++; + phandle = chandle; + chandle = 0; + parent = child; + } + } + } + + return_VALUE(0); +} + + +static int +acpi_bus_scan_fixed ( + struct acpi_device *root) +{ + int result = 0; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_bus_scan"); + + if (!root) + return_VALUE(-ENODEV); + + /* + * Enumerate all fixed-feature devices. + */ + if (acpi_fadt.pwr_button == 0) + result = acpi_bus_add(&device, acpi_root, + ACPI_ROOT_OBJECT, ACPI_BUS_TYPE_POWER_BUTTON); + + if (acpi_fadt.sleep_button == 0) + result = acpi_bus_add(&device, acpi_root, + ACPI_ROOT_OBJECT, ACPI_BUS_TYPE_SLEEP_BUTTON); + + return_VALUE(result); +} + + +/* -------------------------------------------------------------------------- + Initialization/Cleanup + -------------------------------------------------------------------------- */ + +int __init +acpi_blacklisted(void) +{ + int i = 0; + int blacklisted = 0; + acpi_table_header table_header; + + while (acpi_blacklist[i].oem_id[0] != '\0') + { + if (!ACPI_SUCCESS(acpi_get_table_header(acpi_blacklist[i].table, 1, &table_header))) { + i++; + continue; + } + + if (strncmp(acpi_blacklist[i].oem_id, table_header.oem_id, 6)) { + i++; + continue; + } + + if (strncmp(acpi_blacklist[i].oem_table_id, table_header.oem_table_id, 8)) { + i++; + continue; + } + + if ((acpi_blacklist[i].oem_revision_predicate == all_versions) + || (acpi_blacklist[i].oem_revision_predicate == less_than_or_equal + && table_header.oem_revision <= acpi_blacklist[i].oem_revision) + || (acpi_blacklist[i].oem_revision_predicate == greater_than_or_equal + && table_header.oem_revision >= acpi_blacklist[i].oem_revision) + || (acpi_blacklist[i].oem_revision_predicate == equal + && table_header.oem_revision == acpi_blacklist[i].oem_revision)) { + + printk(KERN_ERR PREFIX "Vendor \"%6.6s\" System \"%8.8s\" " + "Revision 0x%x has a known ACPI BIOS problem.\n", + acpi_blacklist[i].oem_id, + acpi_blacklist[i].oem_table_id, + acpi_blacklist[i].oem_revision); + + printk(KERN_ERR PREFIX "Reason: %s. This is a %s error\n", + acpi_blacklist[i].reason, + (acpi_blacklist[i].is_critical_error ? "non-recoverable" : "recoverable")); + + blacklisted = acpi_blacklist[i].is_critical_error; + break; + } + else { + i++; + } + } + + return blacklisted; +} + +static int __init +acpi_bus_init_irq (void) +{ + acpi_status status = AE_OK; + acpi_object arg = {ACPI_TYPE_INTEGER}; + acpi_object_list arg_list = {1, &arg}; + char *message = NULL; + + ACPI_FUNCTION_TRACE("acpi_bus_init_irq"); + + /* + * Let the system know what interrupt model we are using by + * evaluating the \_PIC object, if exists. + */ + + switch (acpi_irq_model) { + case ACPI_IRQ_MODEL_PIC: + message = "PIC"; + break; + case ACPI_IRQ_MODEL_IOAPIC: + message = "IOAPIC"; + break; + case ACPI_IRQ_MODEL_IOSAPIC: + message = "IOSAPIC"; + break; + default: + printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n"); + return_VALUE(-ENODEV); + } + + printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message); + + arg.integer.value = acpi_irq_model; + + status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL); + if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PIC\n")); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +static int __init +acpi_bus_init (void) +{ + int result = 0; + acpi_status status = AE_OK; + acpi_buffer buffer = {sizeof(acpi_fadt), &acpi_fadt}; + int progress = 0; + + ACPI_FUNCTION_TRACE("acpi_bus_init"); + + /* + * [0] Initailize the ACPI Core Subsystem. + */ + status = acpi_initialize_subsystem(); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to initialize the ACPI Interpreter\n"); + result = -ENODEV; + goto end; + } + + progress++; + + /* + * [1] Load the ACPI tables. + */ + status = acpi_load_tables(); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to load the System Description Tables\n"); + result = -ENODEV; + goto end; + } + + progress++; + + /* + * [2] Check the blacklist + */ + if (acpi_blacklisted()) { + result = -ENODEV; + goto end; + } + + progress++; + + /* + * [3] Get a separate copy of the FADT for use by other drivers. + */ + status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to get the FADT\n"); + result = -ENODEV; + goto end; + } + + progress++; + + /* + * [4] Enable the ACPI Core Subsystem. + */ + status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to start the ACPI Interpreter\n"); + result = -ENODEV; + goto end; + } + + printk(KERN_INFO PREFIX "Interpreter enabled\n"); + + progress++; + + /* + * [5] Get the system interrupt model and evaluate \_PIC. + */ + result = acpi_bus_init_irq(); + if (result) + goto end; + + progress++; + + /* + * [6] Register for all standard device notifications. + */ + status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to register for device notifications\n"); + result = -ENODEV; + goto end; + } + + progress++; + + /* + * [7] Create the root device. + */ + result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, + ACPI_BUS_TYPE_SYSTEM); + if (result) + goto end; + + progress++; + + /* + * [8] Create the root file system. + */ + acpi_device_dir(acpi_root) = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL); + if (!acpi_root) { + result = -ENODEV; + goto end; + } + acpi_root_dir = acpi_device_dir(acpi_root); + + progress++; + + /* + * [9] Install drivers required for proper enumeration of the + * ACPI namespace. + */ + acpi_system_init(); /* ACPI System */ + acpi_power_init(); /* ACPI Bus Power Management */ +#ifdef CONFIG_ACPI_EC + acpi_ec_init(); /* ACPI Embedded Controller */ +#endif +#ifdef CONFIG_ACPI_PCI + acpi_pci_link_init(); /* ACPI PCI Interrupt Link */ + acpi_pci_root_init(); /* ACPI PCI Root Bridge */ +#endif + progress++; + + /* + * [10] Enumerate devices in the ACPI namespace. + */ + result = acpi_bus_scan_fixed(acpi_root); + if (result) + goto end; + result = acpi_bus_scan(acpi_root); + if (result) + goto end; + +end: + /* + * Clean up if anything went awry. + */ + if (result) { + switch (progress) { + case 10: + case 9: remove_proc_entry("ACPI", NULL); + case 8: acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL); + case 7: acpi_remove_notify_handler(ACPI_ROOT_OBJECT, + ACPI_SYSTEM_NOTIFY, &acpi_bus_notify); + case 6: + case 5: + case 4: + case 3: + case 2: acpi_terminate(); + case 1: + case 0: + default: return_VALUE(-ENODEV); + } + } + + return_VALUE(0); +} + + +static void __exit +acpi_bus_exit (void) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_bus_exit"); + + status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT, + ACPI_SYSTEM_NOTIFY, acpi_bus_notify); + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + +#ifdef CONFIG_ACPI_PCI + acpi_pci_root_exit(); + acpi_pci_link_exit(); +#endif +#ifdef CONFIG_ACPI_EC + acpi_ec_exit(); +#endif + acpi_power_exit(); + acpi_system_exit(); + + acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL); + + remove_proc_entry(ACPI_BUS_FILE_ROOT, NULL); + + status = acpi_terminate(); + if (ACPI_FAILURE(status)) + printk(KERN_ERR PREFIX "Unable to terminate the ACPI Interpreter\n"); + else + printk(KERN_ERR PREFIX "Interpreter disabled\n"); + + return_VOID; +} + + +int __init +acpi_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_init"); + + printk(KERN_INFO PREFIX "Subsystem revision %08x\n", + ACPI_CA_VERSION); + + /* Initial core debug level excludes drivers, so include them now */ + acpi_set_debug(ACPI_DEBUG_LOW); + + if (acpi_disabled) { + printk(KERN_INFO PREFIX "Disabled via command line (acpi=off)\n"); + return -ENODEV; + } + +#ifdef CONFIG_PM + if (PM_IS_ACTIVE()) { + printk(KERN_INFO PREFIX "APM is already active, exiting\n"); + return -ENODEV; + } +#endif + + result = acpi_bus_init(); + if (result) + return_VALUE(result); + +#ifdef CONFIG_PM + pm_active = 1; +#endif + + return_VALUE(0); +} + + +void __exit +acpi_exit (void) +{ + ACPI_FUNCTION_TRACE("acpi_exit"); + +#ifdef CONFIG_PM + pm_active = 0; +#endif + + acpi_bus_exit(); + + return_VOID; +} + + +int __init +acpi_setup(char *str) +{ + while (str && *str) { + if (strncmp(str, "off", 3) == 0) + acpi_disabled = 1; + str = strchr(str, ','); + if (str) + str += strspn(str, ", \t"); + } + return 1; +} + +subsys_initcall(acpi_init); + +__setup("acpi=", acpi_setup); diff -Nru a/drivers/acpi/button.c b/drivers/acpi/button.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/button.c Sun Jun 2 18:44:56 2002 @@ -0,0 +1,446 @@ +/* + * acpi_button.c - ACPI Button Driver ($Revision: 29 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_BUTTON_COMPONENT +ACPI_MODULE_NAME ("acpi_button") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + + +int acpi_button_add (struct acpi_device *device); +int acpi_button_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_button_driver = { + name: ACPI_BUTTON_DRIVER_NAME, + class: ACPI_BUTTON_CLASS, + ids: "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E", + ops: { + add: acpi_button_add, + remove: acpi_button_remove, + }, +}; + +struct acpi_button { + acpi_handle handle; + struct acpi_device *device; /* Fixed button kludge */ + u8 type; + unsigned long pushed; +}; + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +static struct proc_dir_entry *acpi_button_dir = NULL; + + +static int +acpi_button_read_info ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_button *button = (struct acpi_button *) data; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_button_read_info"); + + if (!button || !button->device) + goto end; + + p += sprintf(p, "type: %s\n", + acpi_device_name(button->device)); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_button_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + struct acpi_button *button = NULL; + + ACPI_FUNCTION_TRACE("acpi_button_add_fs"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + button = acpi_driver_data(device); + + if (!acpi_button_dir) { + acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); + if (!acpi_button_dir) + return_VALUE(-ENODEV); + } + + switch (button->type) { + case ACPI_BUTTON_TYPE_POWER: + case ACPI_BUTTON_TYPE_POWERF: + entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, + acpi_button_dir); + break; + case ACPI_BUTTON_TYPE_SLEEP: + case ACPI_BUTTON_TYPE_SLEEPF: + entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, + acpi_button_dir); + break; + case ACPI_BUTTON_TYPE_LID: + entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, + acpi_button_dir); + break; + } + + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + + /* 'info' [R] */ + entry = create_proc_entry(ACPI_BUTTON_FILE_INFO, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BUTTON_FILE_INFO)); + else { + entry->read_proc = acpi_button_read_info; + entry->data = acpi_driver_data(device); + } + + return_VALUE(0); +} + + +static int +acpi_button_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_button_remove_fs"); + + if (!acpi_button_dir) + return_VALUE(-ENODEV); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_button_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +void +acpi_button_notify ( + acpi_handle handle, + u32 event, + void *data) +{ + struct acpi_button *button = (struct acpi_button *) data; + + ACPI_FUNCTION_TRACE("acpi_button_notify"); + + if (!button || !button->device) + return_VOID; + + switch (event) { + case ACPI_BUTTON_NOTIFY_STATUS: + acpi_bus_generate_event(button->device, event, ++button->pushed); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return_VOID; +} + + +acpi_status +acpi_button_notify_fixed ( + void *data) +{ + struct acpi_button *button = (struct acpi_button *) data; + + ACPI_FUNCTION_TRACE("acpi_button_notify_fixed"); + + if (!button) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button); + + return_ACPI_STATUS(AE_OK); +} + + +int +acpi_button_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_button *button = NULL; + + static struct acpi_device *power_button; + static struct acpi_device *sleep_button; + static struct acpi_device *lid_button; + + ACPI_FUNCTION_TRACE("acpi_button_add"); + + if (!device) + return_VALUE(-EINVAL); + + button = kmalloc(sizeof(struct acpi_button), GFP_KERNEL); + if (!button) + return_VALUE(-ENOMEM); + memset(button, 0, sizeof(struct acpi_button)); + + button->device = device; + button->handle = device->handle; + acpi_driver_data(device) = button; + + /* + * Determine the button type (via hid), as fixed-feature buttons + * need to be handled a bit differently than generic-space. + */ + if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) { + button->type = ACPI_BUTTON_TYPE_POWER; + sprintf(acpi_device_name(device), "%s", + ACPI_BUTTON_DEVICE_NAME_POWER); + sprintf(acpi_device_class(device), "%s/%s", + ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); + } + else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) { + button->type = ACPI_BUTTON_TYPE_POWERF; + sprintf(acpi_device_name(device), "%s", + ACPI_BUTTON_DEVICE_NAME_POWERF); + sprintf(acpi_device_class(device), "%s/%s", + ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); + } + else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) { + button->type = ACPI_BUTTON_TYPE_SLEEP; + sprintf(acpi_device_name(device), "%s", + ACPI_BUTTON_DEVICE_NAME_SLEEP); + sprintf(acpi_device_class(device), "%s/%s", + ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); + } + else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) { + button->type = ACPI_BUTTON_TYPE_SLEEPF; + sprintf(acpi_device_name(device), "%s", + ACPI_BUTTON_DEVICE_NAME_SLEEPF); + sprintf(acpi_device_class(device), "%s/%s", + ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); + } + else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) { + button->type = ACPI_BUTTON_TYPE_LID; + sprintf(acpi_device_name(device), "%s", + ACPI_BUTTON_DEVICE_NAME_LID); + sprintf(acpi_device_class(device), "%s/%s", + ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID); + } + else { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unsupported hid [%s]\n", + acpi_device_hid(device))); + result = -ENODEV; + goto end; + } + + /* + * Ensure only one button of each type is used. + */ + switch (button->type) { + case ACPI_BUTTON_TYPE_POWER: + case ACPI_BUTTON_TYPE_POWERF: + if (!power_button) + power_button = device; + else { + kfree(button); + return_VALUE(-ENODEV); + } + break; + case ACPI_BUTTON_TYPE_SLEEP: + case ACPI_BUTTON_TYPE_SLEEPF: + if (!sleep_button) + sleep_button = device; + else { + kfree(button); + return_VALUE(-ENODEV); + } + break; + case ACPI_BUTTON_TYPE_LID: + if (!lid_button) + lid_button = device; + else { + kfree(button); + return_VALUE(-ENODEV); + } + break; + } + + result = acpi_button_add_fs(device); + if (result) + goto end; + + switch (button->type) { + case ACPI_BUTTON_TYPE_POWERF: + status = acpi_install_fixed_event_handler ( + ACPI_EVENT_POWER_BUTTON, + acpi_button_notify_fixed, + button); + break; + case ACPI_BUTTON_TYPE_SLEEPF: + status = acpi_install_fixed_event_handler ( + ACPI_EVENT_SLEEP_BUTTON, + acpi_button_notify_fixed, + button); + break; + default: + status = acpi_install_notify_handler ( + button->handle, + ACPI_DEVICE_NOTIFY, + acpi_button_notify, + button); + break; + } + + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing notify handler\n")); + result = -ENODEV; + goto end; + } + + printk(KERN_INFO PREFIX "%s [%s]\n", + acpi_device_name(device), acpi_device_bid(device)); + +end: + if (result) { + acpi_button_remove_fs(device); + kfree(button); + } + + return_VALUE(result); +} + + +int +acpi_button_remove (struct acpi_device *device, int type) +{ + acpi_status status = 0; + struct acpi_button *button = NULL; + + ACPI_FUNCTION_TRACE("acpi_button_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + button = acpi_driver_data(device); + + /* Unregister for device notifications. */ + switch (button->type) { + case ACPI_BUTTON_TYPE_POWERF: + status = acpi_remove_fixed_event_handler( + ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed); + break; + case ACPI_BUTTON_TYPE_SLEEPF: + status = acpi_remove_fixed_event_handler( + ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed); + break; + default: + status = acpi_remove_notify_handler(button->handle, + ACPI_DEVICE_NOTIFY, acpi_button_notify); + break; + } + + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + + acpi_button_remove_fs(device); + + kfree(button); + + return_VALUE(0); +} + + +static int __init +acpi_button_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_button_init"); + + result = acpi_bus_register_driver(&acpi_button_driver); + if (result < 0) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + + +static void __exit +acpi_button_exit (void) +{ + ACPI_FUNCTION_TRACE("acpi_button_exit"); + + acpi_bus_unregister_driver(&acpi_button_driver); + + return_VOID; +} + + +module_init(acpi_button_init); +module_exit(acpi_button_exit); diff -Nru a/drivers/acpi/debugger/dbcmds.c b/drivers/acpi/debugger/dbcmds.c --- a/drivers/acpi/debugger/dbcmds.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/debugger/dbcmds.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dbcmds - debug commands and output routines - * $Revision: 79 $ + * $Revision: 83 $ * ******************************************************************************/ @@ -25,15 +25,11 @@ #include "acpi.h" -#include "acparser.h" #include "acdispat.h" #include "amlcode.h" #include "acnamesp.h" -#include "acparser.h" #include "acevents.h" -#include "acinterp.h" #include "acdebug.h" -#include "actables.h" #include "acresrc.h" #ifdef ENABLE_DEBUGGER @@ -47,7 +43,7 @@ * These object types map directly to the ACPI_TYPES */ -ARGUMENT_INFO acpi_db_object_types [] = +static ARGUMENT_INFO acpi_db_object_types [] = { {"ANY"}, {"NUMBERS"}, {"STRINGS"}, @@ -97,13 +93,13 @@ /* Check for match against the namespace node itself */ if (node == (void *) obj_desc) { - acpi_os_printf ("Object is a Node [%4.4s]\n", &node->name); + acpi_os_printf ("Object is a Node [%4.4s]\n", node->name.ascii); } /* Check for match against the object attached to the node */ if (acpi_ns_get_attached_object (node) == obj_desc) { - acpi_os_printf ("Reference at Node->Object %p [%4.4s]\n", node, &node->name); + acpi_os_printf ("Reference at Node->Object %p [%4.4s]\n", node, node->name.ascii); } return (AE_OK); @@ -135,7 +131,7 @@ /* Search all nodes in namespace */ - acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + (void) acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, acpi_db_walk_for_references, (void *) obj_desc, NULL); } @@ -275,8 +271,8 @@ /* Get and verify the breakpoint address */ address = ACPI_STRTOUL (location, NULL, 16); - if (address <= op->aml_offset) { - acpi_os_printf ("Breakpoint %X is beyond current address %X\n", address, op->aml_offset); + if (address <= op->common.aml_offset) { + acpi_os_printf ("Breakpoint %X is beyond current address %X\n", address, op->common.aml_offset); } /* Save breakpoint in current walk */ @@ -482,6 +478,7 @@ u32 value) { acpi_namespace_node *node; + acpi_status status; /* Translate name to an Named object */ @@ -499,7 +496,10 @@ /* Send the notify */ - acpi_ev_queue_notify_request (node, value); + status = acpi_ev_queue_notify_request (node, value); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not queue notify\n"); + } break; default: @@ -536,6 +536,7 @@ u32 value; acpi_walk_state *walk_state; acpi_operand_object *obj_desc; + acpi_status status; /* Validate Type_arg */ @@ -578,12 +579,16 @@ /* Set a method argument */ - if (index > MTH_NUM_ARGS) { + if (index > MTH_MAX_ARG) { acpi_os_printf ("Arg%d - Invalid argument name\n", index); return; } - acpi_ds_store_object_to_local (AML_ARG_OP, index, obj_desc, walk_state); + status = acpi_ds_store_object_to_local (AML_ARG_OP, index, obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + return; + } + obj_desc = walk_state->arguments[index].object; acpi_os_printf ("Arg%d: ", index); @@ -594,12 +599,16 @@ /* Set a method local */ - if (index > MTH_NUM_LOCALS) { + if (index > MTH_MAX_LOCAL) { acpi_os_printf ("Local%d - Invalid local variable name\n", index); return; } - acpi_ds_store_object_to_local (AML_LOCAL_OP, index, obj_desc, walk_state); + status = acpi_ds_store_object_to_local (AML_LOCAL_OP, index, obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + return; + } + obj_desc = walk_state->local_variables[index].object; acpi_os_printf ("Local%d: ", index); @@ -678,6 +687,10 @@ case ACPI_TYPE_BUFFER: acpi_os_printf (" Length %X", obj_desc->buffer.length); break; + + default: + /* Ignore other object types */ + break; } } @@ -722,7 +735,7 @@ /* Walk the namespace from the root */ - acpi_walk_namespace (type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + (void) acpi_walk_namespace (type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, acpi_db_walk_for_specific_objects, (void *) &type, NULL); acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); @@ -762,7 +775,7 @@ /* Wildcard support */ if ((requested_name[i] != '?') && - (requested_name[i] != ((NATIVE_CHAR *) (&((acpi_namespace_node *) obj_handle)->name))[i])) { + (requested_name[i] != ((acpi_namespace_node *) obj_handle)->name.ascii[i])) { /* No match, just exit */ return (AE_OK); @@ -812,7 +825,7 @@ /* Walk the namespace from the root */ - acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + (void) acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, acpi_db_walk_and_match_name, name_arg, NULL); acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); @@ -899,7 +912,8 @@ acpi_db_display_resources ( NATIVE_CHAR *object_arg) { -#ifndef _IA16 +#if ACPI_MACHINE_WIDTH != 16 + acpi_operand_object *obj_desc; acpi_status status; acpi_buffer return_obj; @@ -964,7 +978,7 @@ } else { - acpi_rs_dump_resource_list ((acpi_resource *) acpi_gbl_db_buffer); + acpi_rs_dump_resource_list (ACPI_CAST_PTR (acpi_resource, acpi_gbl_db_buffer)); } status = acpi_set_current_resources (obj_desc, &return_obj); @@ -997,7 +1011,7 @@ } else { - acpi_rs_dump_resource_list ((acpi_resource *) acpi_gbl_db_buffer); + acpi_rs_dump_resource_list (ACPI_CAST_PTR (acpi_resource, acpi_gbl_db_buffer)); } @@ -1009,5 +1023,90 @@ } + +typedef struct +{ + u32 nodes; + u32 objects; +} ACPI_INTEGRITY_INFO; + +/******************************************************************************* + * + * FUNCTION: Acpi_db_integrity_walk + * + * PARAMETERS: Callback from Walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Examine one NS node for valid values. + * + ******************************************************************************/ + +acpi_status +acpi_db_integrity_walk ( + acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value) +{ + ACPI_INTEGRITY_INFO *info = (ACPI_INTEGRITY_INFO *) context; + acpi_namespace_node *node = (acpi_namespace_node *) obj_handle; + acpi_operand_object *object; + + + info->nodes++; + if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) { + acpi_os_printf ("Invalid Descriptor Type for Node %p, Type = %X\n", + node, ACPI_GET_DESCRIPTOR_TYPE (node)); + } + + if (node->type > INTERNAL_TYPE_MAX) { + acpi_os_printf ("Invalid Object Type for Node %p, Type = %X\n", + node, node->type); + } + + if (!acpi_ut_valid_acpi_name (node->name.integer)) { + acpi_os_printf ("Invalid Acpi_name for Node %p\n", node); + } + + object = acpi_ns_get_attached_object (node); + if (object) { + info->objects++; + if (ACPI_GET_DESCRIPTOR_TYPE (object) != ACPI_DESC_TYPE_OPERAND) { + acpi_os_printf ("Invalid Descriptor Type for Object %p, Type = %X\n", + object, ACPI_GET_DESCRIPTOR_TYPE (object)); + } + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_check_integrity + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Check entire namespace for data structure integrity + * + ******************************************************************************/ + +void +acpi_db_check_integrity (void) +{ + ACPI_INTEGRITY_INFO info = {0,0}; + + /* Search all nodes in namespace */ + + (void) acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + acpi_db_integrity_walk, (void *) &info, NULL); + + acpi_os_printf ("Verified %d namespace nodes with %d Objects\n", info.nodes, info.objects); + +} #endif /* ENABLE_DEBUGGER */ diff -Nru a/drivers/acpi/debugger/dbdisasm.c b/drivers/acpi/debugger/dbdisasm.c --- a/drivers/acpi/debugger/dbdisasm.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/debugger/dbdisasm.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dbdisasm - parser op tree display routines - * $Revision: 61 $ + * $Revision: 66 $ * ******************************************************************************/ @@ -40,7 +40,7 @@ #define BLOCK_PAREN 1 #define BLOCK_BRACE 2 #define DB_NO_OP_INFO " [%2.2d] " -#define DB_FULL_OP_INFO "%5.5X #%4.4X [%2.2d] " +#define DB_FULL_OP_INFO "%5.5X #%4.4hX [%2.2d] " NATIVE_CHAR *acpi_gbl_db_disasm_indent = "...."; @@ -63,7 +63,7 @@ acpi_parse_object *op) { - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_METHOD_OP: return (BLOCK_BRACE); @@ -101,15 +101,15 @@ char *name; - if (op->flags & ACPI_PARSEOP_GENERIC) { - name = op->value.name; + if (op->common.flags & ACPI_PARSEOP_GENERIC) { + name = op->common.value.name; if (name[0] == '\\') { acpi_os_printf (" (Fully Qualified Pathname)"); return (AE_OK); } } else { - name = (char *) &((acpi_parse2_object *) op)->name; + name = (char *) &op->named.name; } /* Search parent tree up to the root if necessary */ @@ -155,11 +155,11 @@ /* Just get the Node out of the Op object */ - node = op->node; + node = op->common.node; if (!node) { /* Node not defined in this scope, look it up */ - status = acpi_ns_lookup (walk_state->scope_info, op->value.string, ACPI_TYPE_ANY, + status = acpi_ns_lookup (walk_state->scope_info, op->common.value.string, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node)); if (ACPI_FAILURE (status)) { @@ -174,7 +174,7 @@ /* Save it for next time. */ - op->node = node; + op->common.node = node; } /* Convert Named_desc/handle to a full pathname */ @@ -244,10 +244,10 @@ /* Determine the nesting depth of this argument */ - for (depth = op->parent; depth; depth = depth->parent) { + for (depth = op->common.parent; depth; depth = depth->common.parent) { arg = acpi_ps_get_arg (depth, 0); while (arg && arg != origin) { - arg = arg->next; + arg = arg->common.next; } if (arg) { @@ -276,9 +276,9 @@ /* Close a block if we are nested less than last time */ else if (depth_count < last_depth) { - for (j = 0; j < (last_depth - depth_count); j++) { - VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth - j)); - for (i = 0; i < (last_depth - j - 1); i++) { + for (j = last_depth; j >= (depth_count + 1); j--) { + VERBOSE_PRINT ((DB_NO_OP_INFO, (j - 1))); + for (i = 1; i < j; i++) { acpi_os_printf ("%s", acpi_gbl_db_disasm_indent); } @@ -293,7 +293,8 @@ /* In verbose mode, print the AML offset, opcode and depth count */ - VERBOSE_PRINT ((DB_FULL_OP_INFO, (unsigned) op->aml_offset, op->opcode, depth_count)); + VERBOSE_PRINT ((DB_FULL_OP_INFO, (u32) op->common.aml_offset, + op->common.aml_opcode, depth_count)); /* Indent the output according to the depth count */ @@ -308,10 +309,10 @@ /* Resolve a name reference */ - if ((op->opcode == AML_INT_NAMEPATH_OP && op->value.name) && - (op->parent) && + if ((op->common.aml_opcode == AML_INT_NAMEPATH_OP && op->common.value.name) && + (op->common.parent) && (acpi_gbl_db_opt_verbose)) { - acpi_ps_display_object_pathname (walk_state, op); + (void) acpi_ps_display_object_pathname (walk_state, op); } acpi_os_printf ("\n"); @@ -438,7 +439,7 @@ /* We are only interested in named objects */ - op_info = acpi_ps_get_opcode_info (op->opcode); + op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); if (!(op_info->flags & AML_NSNODE)) { return; } @@ -446,7 +447,7 @@ if (op_info->flags & AML_CREATE) { /* Field creation - check for a fully qualified namepath */ - if (op->opcode == AML_CREATE_FIELD_OP) { + if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { name_path = acpi_ps_get_arg (op, 3); } else { @@ -454,9 +455,9 @@ } if ((name_path) && - (name_path->value.string) && - (name_path->value.string[0] == '\\')) { - acpi_db_display_namestring (name_path->value.string); + (name_path->common.value.string) && + (name_path->common.value.string[0] == '\\')) { + acpi_db_display_namestring (name_path->common.value.string); return; } } @@ -468,17 +469,17 @@ search = op; for (; ;) { - if (search->parent == prev) { + if (search->common.parent == prev) { break; } /* Go up one level */ - search = search->parent; + search = search->common.parent; } if (prev) { - op_info = acpi_ps_get_opcode_info (search->opcode); + op_info = acpi_ps_get_opcode_info (search->common.aml_opcode); if (!(op_info->flags & AML_FIELD)) { /* below root scope, append scope name */ @@ -489,7 +490,7 @@ } if (op_info->flags & AML_CREATE) { - if (op->opcode == AML_CREATE_FIELD_OP) { + if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { name_path = acpi_ps_get_arg (op, 3); } else { @@ -497,8 +498,8 @@ } if ((name_path) && - (name_path->value.string)) { - acpi_os_printf ("%4.4s", name_path->value.string); + (name_path->common.value.string)) { + acpi_os_printf ("%4.4s", name_path->common.value.string); } } else { @@ -544,18 +545,19 @@ if (!op) { acpi_os_printf (""); + return; } /* op and arguments */ - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_BYTE_OP: if (acpi_gbl_db_opt_verbose) { - acpi_os_printf ("(u8) 0x%2.2X", op->value.integer8); + acpi_os_printf ("(u8) 0x%2.2hX", op->common.value.integer8); } else { - acpi_os_printf ("0x%2.2X", op->value.integer8); + acpi_os_printf ("0x%2.2hX", op->common.value.integer8); } break; @@ -563,10 +565,10 @@ case AML_WORD_OP: if (acpi_gbl_db_opt_verbose) { - acpi_os_printf ("(u16) 0x%4.4X", op->value.integer16); + acpi_os_printf ("(u16) 0x%4.4hX", op->common.value.integer16); } else { - acpi_os_printf ("0x%4.4X", op->value.integer16); + acpi_os_printf ("0x%4.4hX", op->common.value.integer16); } break; @@ -574,10 +576,10 @@ case AML_DWORD_OP: if (acpi_gbl_db_opt_verbose) { - acpi_os_printf ("(u32) 0x%8.8X", op->value.integer32); + acpi_os_printf ("(u32) 0x%8.8X", op->common.value.integer32); } else { - acpi_os_printf ("0x%8.8X", op->value.integer32); + acpi_os_printf ("0x%8.8X", op->common.value.integer32); } break; @@ -585,20 +587,20 @@ case AML_QWORD_OP: if (acpi_gbl_db_opt_verbose) { - acpi_os_printf ("(u64) 0x%8.8X%8.8X", op->value.integer64.hi, - op->value.integer64.lo); + acpi_os_printf ("(u64) 0x%8.8X%8.8X", op->common.value.integer64.hi, + op->common.value.integer64.lo); } else { - acpi_os_printf ("0x%8.8X%8.8X", op->value.integer64.hi, - op->value.integer64.lo); + acpi_os_printf ("0x%8.8X%8.8X", op->common.value.integer64.hi, + op->common.value.integer64.lo); } break; case AML_STRING_OP: - if (op->value.string) { - acpi_os_printf ("\"%s\"", op->value.string); + if (op->common.value.string) { + acpi_os_printf ("\"%s\"", op->common.value.string); } else { acpi_os_printf ("<\"NULL STRING PTR\">"); @@ -608,8 +610,8 @@ case AML_INT_STATICSTRING_OP: - if (op->value.string) { - acpi_os_printf ("\"%s\"", op->value.string); + if (op->common.value.string) { + acpi_os_printf ("\"%s\"", op->common.value.string); } else { acpi_os_printf ("\"\""); @@ -619,38 +621,38 @@ case AML_INT_NAMEPATH_OP: - acpi_db_display_namestring (op->value.name); + acpi_db_display_namestring (op->common.value.name); break; case AML_INT_NAMEDFIELD_OP: - acpi_os_printf ("Named_field (Length 0x%8.8X) ", op->value.integer32); + acpi_os_printf ("Named_field (Length 0x%8.8X) ", op->common.value.integer32); break; case AML_INT_RESERVEDFIELD_OP: - acpi_os_printf ("Reserved_field (Length 0x%8.8X) ", op->value.integer32); + acpi_os_printf ("Reserved_field (Length 0x%8.8X) ", op->common.value.integer32); break; case AML_INT_ACCESSFIELD_OP: - acpi_os_printf ("Access_field (Length 0x%8.8X) ", op->value.integer32); + acpi_os_printf ("Access_field (Length 0x%8.8X) ", op->common.value.integer32); break; case AML_INT_BYTELIST_OP: if (acpi_gbl_db_opt_verbose) { - acpi_os_printf ("Byte_list (Length 0x%8.8X) ", op->value.integer32); + acpi_os_printf ("Byte_list (Length 0x%8.8X) ", op->common.value.integer32); } else { - acpi_os_printf ("0x%2.2X", op->value.integer32); + acpi_os_printf ("0x%2.2X", op->common.value.integer32); - byte_count = op->value.integer32; - byte_data = ((acpi_parse2_object *) op)->data; + byte_count = op->common.value.integer32; + byte_data = op->named.data; for (i = 0; i < byte_count; i++) { acpi_os_printf (", 0x%2.2X", byte_data[i]); @@ -663,12 +665,13 @@ /* Just get the opcode name and print it */ - op_info = acpi_ps_get_opcode_info (op->opcode); + op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); acpi_os_printf ("%s", op_info->name); #ifndef PARSER_ONLY - if ((op->opcode == AML_INT_RETURN_VALUE_OP) && + if ((op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) && + (walk_state) && (walk_state->results) && (walk_state->results->results.num_results)) { acpi_db_decode_internal_object (walk_state->results->results.obj_desc [walk_state->results->results.num_results-1]); @@ -680,7 +683,7 @@ if (!op_info) { /* If there is another element in the list, add a comma */ - if (op->next) { + if (op->common.next) { acpi_os_printf (","); } } @@ -688,13 +691,13 @@ /* * If this is a named opcode, print the associated name value */ - op_info = acpi_ps_get_opcode_info (op->opcode); + op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); if (op && (op_info->flags & AML_NAMED)) { name = acpi_ps_get_name (op); acpi_os_printf (" %4.4s", &name); - if ((acpi_gbl_db_opt_verbose) && (op->opcode != AML_INT_NAMEDFIELD_OP)) { - acpi_ps_display_object_pathname (walk_state, op); + if ((acpi_gbl_db_opt_verbose) && (op->common.aml_opcode != AML_INT_NAMEDFIELD_OP)) { + (void) acpi_ps_display_object_pathname (walk_state, op); } } } diff -Nru a/drivers/acpi/debugger/dbdisply.c b/drivers/acpi/debugger/dbdisply.c --- a/drivers/acpi/debugger/dbdisply.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/debugger/dbdisply.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dbdisply - debug display commands - * $Revision: 67 $ + * $Revision: 73 $ * ******************************************************************************/ @@ -25,12 +25,10 @@ #include "acpi.h" -#include "acparser.h" #include "amlcode.h" #include "acdispat.h" #include "acnamesp.h" #include "acparser.h" -#include "acevents.h" #include "acinterp.h" #include "acdebug.h" @@ -61,7 +59,7 @@ void *obj_ptr; -#ifdef _IA16 +#if ACPI_MACHINE_WIDTH == 16 #include /* Have to handle 16-bit pointers of the form segment:offset */ @@ -101,16 +99,16 @@ const acpi_opcode_info *info; - info = acpi_ps_get_opcode_info (op->opcode); + info = acpi_ps_get_opcode_info (op->common.aml_opcode); acpi_os_printf ("Parser Op Descriptor:\n"); - acpi_os_printf ("%20.20s : %4.4X\n", "Opcode", op->opcode); + acpi_os_printf ("%20.20s : %4.4X\n", "Opcode", op->common.aml_opcode); ACPI_DEBUG_ONLY_MEMBERS (acpi_os_printf ("%20.20s : %s\n", "Opcode Name", info->name)); - acpi_os_printf ("%20.20s : %p\n", "Value/Arg_list", op->value); - acpi_os_printf ("%20.20s : %p\n", "Parent", op->parent); - acpi_os_printf ("%20.20s : %p\n", "Next_op", op->next); + acpi_os_printf ("%20.20s : %p\n", "Value/Arg_list", op->common.value.arg); + acpi_os_printf ("%20.20s : %p\n", "Parent", op->common.parent); + acpi_os_printf ("%20.20s : %p\n", "Next_op", op->common.next); } @@ -190,7 +188,7 @@ goto dump_nte; - case ACPI_DESC_TYPE_INTERNAL: + case ACPI_DESC_TYPE_OPERAND: /* This is a ACPI OPERAND OBJECT */ @@ -266,7 +264,7 @@ obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { - acpi_os_printf ("\n_attached Object (%p):\n", obj_desc); + acpi_os_printf ("\nAttached Object (%p):\n", obj_desc); if (!acpi_os_readable (obj_desc, sizeof (acpi_operand_object))) { acpi_os_printf ("Invalid internal ACPI Object at address %p\n", obj_desc); return; @@ -307,8 +305,8 @@ switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: - acpi_os_printf (" %.8X%.8X", ACPI_HIDWORD (obj_desc->integer.value), - ACPI_LODWORD (obj_desc->integer.value)); + acpi_os_printf (" %8.8X%8.8X", ACPI_HIDWORD (obj_desc->integer.value), + ACPI_LODWORD (obj_desc->integer.value)); break; @@ -335,6 +333,11 @@ acpi_os_printf (" %2.2X", obj_desc->buffer.pointer[i]); } break; + + + default: + /* No additional display for other types */ + break; } } @@ -379,7 +382,7 @@ case ACPI_DESC_TYPE_NAMED: acpi_os_printf (" Name %4.4s Type-%s", - &((acpi_namespace_node *)obj_desc)->name, + ((acpi_namespace_node *)obj_desc)->name.ascii, acpi_ut_get_type_name (((acpi_namespace_node *) obj_desc)->type)); if (((acpi_namespace_node *) obj_desc)->flags & ANOBJ_METHOD_ARG) { @@ -391,11 +394,11 @@ break; - case ACPI_DESC_TYPE_INTERNAL: + case ACPI_DESC_TYPE_OPERAND: type = obj_desc->common.type; if (type > INTERNAL_TYPE_MAX) { - acpi_os_printf (" Type %x [Invalid Type]", type); + acpi_os_printf (" Type %hX [Invalid Type]", type); return; } @@ -517,13 +520,13 @@ num_args = obj_desc->method.param_count; concurrency = obj_desc->method.concurrency; - acpi_os_printf ("Currently executing control method is [%4.4s]\n", &node->name); + acpi_os_printf ("Currently executing control method is [%4.4s]\n", node->name.ascii); acpi_os_printf ("%X arguments, max concurrency = %X\n", num_args, concurrency); root_op = start_op; - while (root_op->parent) { - root_op = root_op->parent; + while (root_op->common.parent) { + root_op = root_op->common.parent; } op = root_op; @@ -540,7 +543,7 @@ /* Decode the opcode */ - op_info = acpi_ps_get_opcode_info (op->opcode); + op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); switch (op_info->class) { case AML_CLASS_ARGUMENT: if (count_remaining) { @@ -604,7 +607,7 @@ obj_desc = walk_state->method_desc; node = walk_state->method_node; - acpi_os_printf ("Local Variables for method [%4.4s]:\n", &node->name); + acpi_os_printf ("Local Variables for method [%4.4s]:\n", node->name.ascii); for (i = 0; i < MTH_NUM_LOCALS; i++) { obj_desc = walk_state->local_variables[i].object; @@ -650,7 +653,7 @@ concurrency = obj_desc->method.concurrency; acpi_os_printf ("Method [%4.4s] has %X arguments, max concurrency = %X\n", - &node->name, num_args, concurrency); + node->name.ascii, num_args, concurrency); for (i = 0; i < num_args; i++) { obj_desc = walk_state->arguments[i].object; @@ -696,7 +699,7 @@ } acpi_os_printf ("Method [%4.4s] has %X stacked result objects\n", - &node->name, num_results); + node->name.ascii, num_results); for (i = 0; i < num_results; i++) { obj_desc = walk_state->results->results.obj_desc[i]; @@ -721,7 +724,6 @@ void acpi_db_display_calling_tree (void) { - u32 i; acpi_walk_state *walk_state; acpi_namespace_node *node; @@ -735,10 +737,10 @@ node = walk_state->method_node; acpi_os_printf ("Current Control Method Call Tree\n"); - for (i = 0; walk_state; i++) { + while (walk_state) { node = walk_state->method_node; - acpi_os_printf (" [%4.4s]\n", &node->name); + acpi_os_printf (" [%4.4s]\n", node->name.ascii); walk_state = walk_state->next; } diff -Nru a/drivers/acpi/debugger/dbexec.c b/drivers/acpi/debugger/dbexec.c --- a/drivers/acpi/debugger/dbexec.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/debugger/dbexec.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dbexec - debugger control method execution - * $Revision: 39 $ + * $Revision: 41 $ * ******************************************************************************/ @@ -25,15 +25,7 @@ #include "acpi.h" -#include "acparser.h" -#include "acdispat.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "acparser.h" -#include "acevents.h" -#include "acinterp.h" #include "acdebug.h" -#include "actables.h" #ifdef ENABLE_DEBUGGER @@ -41,7 +33,7 @@ ACPI_MODULE_NAME ("dbexec") -acpi_db_method_info acpi_gbl_db_method_info; +static acpi_db_method_info acpi_gbl_db_method_info; /******************************************************************************* @@ -127,7 +119,7 @@ void acpi_db_execute_setup ( - acpi_db_method_info *info) + acpi_db_method_info *info) { /* Catenate the current scope to the supplied name */ @@ -172,7 +164,8 @@ ******************************************************************************/ u32 -acpi_db_get_outstanding_allocations (void) +acpi_db_get_outstanding_allocations ( + void) { u32 outstanding = 0; @@ -309,7 +302,10 @@ /* Signal our completion */ - acpi_os_signal_semaphore (info->thread_gate, 1); + status = acpi_os_signal_semaphore (info->thread_gate, 1); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not signal debugger semaphore\n"); + } } @@ -373,7 +369,10 @@ acpi_os_printf ("Creating %X threads to execute %X times each\n", num_threads, num_loops); for (i = 0; i < (num_threads); i++) { - acpi_os_queue_for_execution (OSD_PRIORITY_MED, acpi_db_method_thread, &acpi_gbl_db_method_info); + status = acpi_os_queue_for_execution (OSD_PRIORITY_MED, acpi_db_method_thread, &acpi_gbl_db_method_info); + if (ACPI_FAILURE (status)) { + break; + } } /* Wait for all threads to complete */ @@ -386,7 +385,7 @@ /* Cleanup and exit */ - acpi_os_delete_semaphore (thread_gate); + (void) acpi_os_delete_semaphore (thread_gate); acpi_db_set_output_destination (ACPI_DB_DUPLICATE_OUTPUT); acpi_os_printf ("All threads (%X) have completed\n", num_threads); diff -Nru a/drivers/acpi/debugger/dbfileio.c b/drivers/acpi/debugger/dbfileio.c --- a/drivers/acpi/debugger/dbfileio.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/debugger/dbfileio.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ * * Module Name: dbfileio - Debugger file I/O commands. These can't usually * be used when running the debugger in Ring 0 (Kernel mode) - * $Revision: 60 $ + * $Revision: 63 $ * ******************************************************************************/ @@ -28,8 +28,6 @@ #include "acpi.h" #include "acdebug.h" #include "acnamesp.h" -#include "acparser.h" -#include "acevents.h" #include "actables.h" #ifdef ENABLE_DEBUGGER @@ -167,7 +165,7 @@ * ******************************************************************************/ -acpi_status +static acpi_status acpi_db_load_table( FILE *fp, acpi_table_header **table_ptr, @@ -285,7 +283,7 @@ table_info.pointer = table_ptr; - status = acpi_tb_install_table (NULL, &table_info); + status = acpi_tb_install_table (&table_info); if (ACPI_FAILURE (status)) { /* Free table allocated by Acpi_tb_get_table */ @@ -371,7 +369,7 @@ if (ACPI_FAILURE (status)) { if (status == AE_ALREADY_EXISTS) { acpi_os_printf ("Table %4.4s is already installed\n", - &acpi_gbl_db_table_ptr->signature); + acpi_gbl_db_table_ptr->signature); } else { acpi_os_printf ("Could not install table, %s\n", @@ -382,7 +380,7 @@ } acpi_os_printf ("%4.4s at %p successfully installed and loaded\n", - &acpi_gbl_db_table_ptr->signature, acpi_gbl_db_table_ptr); + acpi_gbl_db_table_ptr->signature, acpi_gbl_db_table_ptr); acpi_gbl_acpi_hardware_present = FALSE; diff -Nru a/drivers/acpi/debugger/dbhistry.c b/drivers/acpi/debugger/dbhistry.c --- a/drivers/acpi/debugger/dbhistry.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/debugger/dbhistry.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dbhistry - debugger HISTORY command - * $Revision: 22 $ + * $Revision: 24 $ * *****************************************************************************/ @@ -25,15 +25,7 @@ #include "acpi.h" -#include "acparser.h" -#include "acdispat.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "acparser.h" -#include "acevents.h" -#include "acinterp.h" #include "acdebug.h" -#include "actables.h" #ifdef ENABLE_DEBUGGER @@ -54,11 +46,11 @@ } HISTORY_INFO; -HISTORY_INFO acpi_gbl_history_buffer[HISTORY_SIZE]; -u16 acpi_gbl_lo_history = 0; -u16 acpi_gbl_num_history = 0; -u16 acpi_gbl_next_history_index = 0; -u32 acpi_gbl_next_cmd_num = 1; +static HISTORY_INFO acpi_gbl_history_buffer[HISTORY_SIZE]; +static u16 acpi_gbl_lo_history = 0; +static u16 acpi_gbl_num_history = 0; +static u16 acpi_gbl_next_history_index = 0; +static u32 acpi_gbl_next_cmd_num = 1; /******************************************************************************* diff -Nru a/drivers/acpi/debugger/dbinput.c b/drivers/acpi/debugger/dbinput.c --- a/drivers/acpi/debugger/dbinput.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/debugger/dbinput.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dbinput - user front-end to the AML debugger - * $Revision: 81 $ + * $Revision: 86 $ * ******************************************************************************/ @@ -25,10 +25,6 @@ #include "acpi.h" -#include "acparser.h" -#include "actables.h" -#include "acnamesp.h" -#include "acinterp.h" #include "acdebug.h" @@ -67,6 +63,7 @@ CMD_HISTORY_EXE, CMD_HISTORY_LAST, CMD_INFORMATION, + CMD_INTEGRITY, CMD_INTO, CMD_LEVEL, CMD_LIST, @@ -97,7 +94,7 @@ #define CMD_FIRST_VALID 2 -const COMMAND_INFO acpi_gbl_db_commands[] = +static const COMMAND_INFO acpi_gbl_db_commands[] = { {"", 0}, {"", 0}, {"ALLOCATIONS", 0}, @@ -120,6 +117,7 @@ {"!", 1}, {"!!", 0}, {"INFORMATION", 0}, + {"INTEGRITY", 0}, {"INTO", 0}, {"LEVEL", 0}, {"LIST", 0}, @@ -190,7 +188,7 @@ switch (help_type[0]) { case 'G': - acpi_os_printf ("\n_general-Purpose Commands\n\n"); + acpi_os_printf ("\nGeneral-Purpose Commands\n\n"); acpi_os_printf ("Allocations Display list of current memory allocations\n"); acpi_os_printf ("Dump
|\n"); acpi_os_printf (" [Byte|Word|Dword|Qword] Display ACPI objects or memory\n"); @@ -209,7 +207,7 @@ return; case 'N': - acpi_os_printf ("\n_namespace Access Commands\n\n"); + acpi_os_printf ("\nNamespace Access Commands\n\n"); acpi_os_printf ("Debug [Arguments] Single Step a control method\n"); acpi_os_printf ("Event Generate Acpi_event (Fixed/GPE)\n"); acpi_os_printf ("Execute [Arguments] Execute control method\n"); @@ -227,7 +225,7 @@ return; case 'M': - acpi_os_printf ("\n_control Method Execution Commands\n\n"); + acpi_os_printf ("\nControl Method Execution Commands\n\n"); acpi_os_printf ("Arguments (or Args) Display method arguments\n"); acpi_os_printf ("Breakpoint Set an AML execution breakpoint\n"); acpi_os_printf ("Call Run to next control method invocation\n"); @@ -244,14 +242,14 @@ return; case 'F': - acpi_os_printf ("\n_file I/O Commands\n\n"); + acpi_os_printf ("\nFile I/O Commands\n\n"); acpi_os_printf ("Close Close debug output file\n"); acpi_os_printf ("Open Open a file for debug output\n"); acpi_os_printf ("Load Load ACPI table from a file\n"); return; default: - acpi_os_printf ("Unrecognized Command Class: %x\n", help_type); + acpi_os_printf ("Unrecognized Command Class: %X\n", help_type); return; } } @@ -526,7 +524,7 @@ break; case CMD_FIND: - acpi_db_find_name_in_namespace (acpi_gbl_db_args[1]); + status = acpi_db_find_name_in_namespace (acpi_gbl_db_args[1]); break; case CMD_GO: @@ -574,6 +572,10 @@ acpi_db_display_method_info (op); break; + case CMD_INTEGRITY: + acpi_db_check_integrity (); + break; + case CMD_INTO: if (op) { @@ -623,7 +625,7 @@ break; case CMD_METHODS: - acpi_db_display_objects ("METHOD", acpi_gbl_db_args[1]); + status = acpi_db_display_objects ("METHOD", acpi_gbl_db_args[1]); break; case CMD_NAMESPACE: @@ -636,7 +638,8 @@ break; case CMD_OBJECT: - acpi_db_display_objects (ACPI_STRUPR (acpi_gbl_db_args[1]), acpi_gbl_db_args[2]); + ACPI_STRUPR (acpi_gbl_db_args[1]); + status = acpi_db_display_objects (acpi_gbl_db_args[1], acpi_gbl_db_args[2]); break; case CMD_OPEN: @@ -668,11 +671,11 @@ break; case CMD_STATS: - acpi_db_display_statistics (acpi_gbl_db_args[1]); + status = acpi_db_display_statistics (acpi_gbl_db_args[1]); break; case CMD_STOP: - return (AE_AML_ERROR); + return (AE_NOT_IMPLEMENTED); case CMD_TABLES: acpi_db_display_table_info (acpi_gbl_db_args[1]); @@ -722,6 +725,7 @@ return (AE_CTRL_TERMINATE); case CMD_NOT_FOUND: + default: acpi_os_printf ("Unknown Command\n"); return (AE_CTRL_TRUE); } @@ -794,13 +798,11 @@ acpi_db_single_thread ( void) { - acpi_status status; - acpi_gbl_method_executing = FALSE; acpi_gbl_step_to_next_call = FALSE; - status = acpi_db_command_dispatch (acpi_gbl_db_line_buf, NULL, NULL); + (void) acpi_db_command_dispatch (acpi_gbl_db_line_buf, NULL, NULL); } @@ -847,8 +849,7 @@ /* Get the user input line */ - acpi_os_get_line (acpi_gbl_db_line_buf); - + (void) acpi_os_get_line (acpi_gbl_db_line_buf); /* Check for single or multithreaded debug */ @@ -882,7 +883,7 @@ * Only this thread (the original thread) should actually terminate the subsystem, * because all the semaphores are deleted during termination */ - acpi_terminate (); + status = acpi_terminate (); return (status); } diff -Nru a/drivers/acpi/debugger/dbstats.c b/drivers/acpi/debugger/dbstats.c --- a/drivers/acpi/debugger/dbstats.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/debugger/dbstats.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dbstats - Generation and display of ACPI table statistics - * $Revision: 55 $ + * $Revision: 59 $ * ******************************************************************************/ @@ -26,8 +26,6 @@ #include #include -#include -#include #include #ifdef ENABLE_DEBUGGER @@ -38,7 +36,7 @@ /* * Statistics subcommands */ -ARGUMENT_INFO acpi_db_stat_types [] = +static ARGUMENT_INFO acpi_db_stat_types [] = { {"ALLOCATIONS"}, {"OBJECTS"}, {"MEMORY"}, @@ -49,13 +47,13 @@ {NULL} /* Must be null terminated */ }; -#define CMD_ALLOCATIONS 0 -#define CMD_OBJECTS 1 -#define CMD_MEMORY 2 -#define CMD_MISC 3 -#define CMD_TABLES 4 -#define CMD_SIZES 5 -#define CMD_STACK 6 +#define CMD_STAT_ALLOCATIONS 0 +#define CMD_STAT_OBJECTS 1 +#define CMD_STAT_MEMORY 2 +#define CMD_STAT_MISC 3 +#define CMD_STAT_TABLES 4 +#define CMD_STAT_SIZES 5 +#define CMD_STAT_STACK 6 /******************************************************************************* @@ -143,6 +141,9 @@ acpi_db_enumerate_object (obj_desc->thermal_zone.drv_handler); acpi_db_enumerate_object (obj_desc->thermal_zone.addr_handler); break; + + default: + break; } } @@ -232,7 +233,7 @@ * ******************************************************************************/ -acpi_status +void acpi_db_count_namespace_objects ( void) { @@ -249,10 +250,8 @@ acpi_gbl_node_type_count [i] = 0; } - acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + (void) acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, FALSE, acpi_db_classify_one_object, NULL, NULL); - - return (AE_OK); } #endif @@ -305,14 +304,14 @@ switch (type) { #ifndef PARSER_ONLY - case CMD_ALLOCATIONS: + case CMD_STAT_ALLOCATIONS: #ifdef ACPI_DBG_TRACK_ALLOCATIONS acpi_ut_dump_allocation_info (); #endif break; #endif - case CMD_TABLES: + case CMD_STAT_TABLES: acpi_os_printf ("ACPI Table Information:\n\n"); if (acpi_gbl_DSDT) @@ -321,13 +320,13 @@ } break; - case CMD_OBJECTS: + case CMD_STAT_OBJECTS: #ifndef PARSER_ONLY acpi_db_count_namespace_objects (); - acpi_os_printf ("\n_objects defined in the current namespace:\n\n"); + acpi_os_printf ("\nObjects defined in the current namespace:\n\n"); acpi_os_printf ("%16.16s % 10.10s % 10.10s\n", "ACPI_TYPE", "NODES", "OBJECTS"); @@ -345,7 +344,7 @@ #endif break; - case CMD_MEMORY: + case CMD_STAT_MEMORY: #ifdef ACPI_DBG_TRACK_ALLOCATIONS acpi_os_printf ("\n----Object and Cache Statistics---------------------------------------------\n"); @@ -391,9 +390,9 @@ break; - case CMD_MISC: + case CMD_STAT_MISC: - acpi_os_printf ("\n_miscellaneous Statistics:\n\n"); + acpi_os_printf ("\nMiscellaneous Statistics:\n\n"); acpi_os_printf ("Calls to Acpi_ps_find:.. ........% 7ld\n", acpi_gbl_ps_find_count); acpi_os_printf ("Calls to Acpi_ns_lookup:..........% 7ld\n", acpi_gbl_ns_lookup_count); @@ -407,9 +406,9 @@ break; - case CMD_SIZES: + case CMD_STAT_SIZES: - acpi_os_printf ("\n_internal object sizes:\n\n"); + acpi_os_printf ("\nInternal object sizes:\n\n"); acpi_os_printf ("Common %3d\n", sizeof (ACPI_OBJECT_COMMON)); acpi_os_printf ("Number %3d\n", sizeof (ACPI_OBJECT_INTEGER)); @@ -436,23 +435,29 @@ acpi_os_printf ("\n"); - acpi_os_printf ("Parse_object %3d\n", sizeof (acpi_parse_object)); - acpi_os_printf ("Parse2_object %3d\n", sizeof (acpi_parse2_object)); + acpi_os_printf ("Parse_object %3d\n", sizeof (ACPI_PARSE_OBJ_COMMON)); + acpi_os_printf ("Parse_object_named %3d\n", sizeof (ACPI_PARSE_OBJ_NAMED)); + acpi_os_printf ("Parse_object_asl %3d\n", sizeof (ACPI_PARSE_OBJ_ASL)); acpi_os_printf ("Operand_object %3d\n", sizeof (acpi_operand_object)); acpi_os_printf ("Namespace_node %3d\n", sizeof (acpi_namespace_node)); break; - case CMD_STACK: + case CMD_STAT_STACK: +#if defined(ACPI_DEBUG) - size = acpi_gbl_entry_stack_pointer - acpi_gbl_lowest_stack_pointer; + size = (u32) (acpi_gbl_entry_stack_pointer - acpi_gbl_lowest_stack_pointer); - acpi_os_printf ("\n_subsystem Stack Usage:\n\n"); + acpi_os_printf ("\nSubsystem Stack Usage:\n\n"); acpi_os_printf ("Entry Stack Pointer %X\n", acpi_gbl_entry_stack_pointer); acpi_os_printf ("Lowest Stack Pointer %X\n", acpi_gbl_lowest_stack_pointer); acpi_os_printf ("Stack Use %X (%d)\n", size, size); acpi_os_printf ("Deepest Procedure Nesting %d\n", acpi_gbl_deepest_nesting); +#endif + break; + + default: break; } diff -Nru a/drivers/acpi/debugger/dbutils.c b/drivers/acpi/debugger/dbutils.c --- a/drivers/acpi/debugger/dbutils.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/debugger/dbutils.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dbutils - AML debugger utilities - * $Revision: 52 $ + * $Revision: 55 $ * ******************************************************************************/ @@ -28,9 +28,6 @@ #include "acparser.h" #include "amlcode.h" #include "acnamesp.h" -#include "acparser.h" -#include "acevents.h" -#include "acinterp.h" #include "acdebug.h" #include "acdispat.h" @@ -87,7 +84,7 @@ u32 address) { - acpi_os_printf ("\n_location %X:\n", address); + acpi_os_printf ("\nLocation %X:\n", address); acpi_dbg_level |= ACPI_LV_TABLES; acpi_ut_dump_buffer (ACPI_TO_POINTER (address), 64, DB_BYTE_DISPLAY, ACPI_UINT32_MAX); @@ -259,7 +256,7 @@ acpi_parse_object *root) { acpi_parse_object *op = root; - acpi_parse2_object *method; + acpi_parse_object *method; acpi_parse_object *search_op; acpi_parse_object *start_op; acpi_status status = AE_OK; @@ -272,10 +269,11 @@ acpi_os_printf ("Pass two parse ....\n"); - while (op) { - if (op->opcode == AML_METHOD_OP) { - method = (acpi_parse2_object *) op; + if (op->common.aml_opcode == AML_METHOD_OP) { + method = op; + + /* Create a new walk state for the parse */ walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); @@ -283,32 +281,32 @@ return (AE_NO_MEMORY); } + /* Init the Walk State */ walk_state->parser_state.aml = - walk_state->parser_state.aml_start = method->data; + walk_state->parser_state.aml_start = method->named.data; walk_state->parser_state.aml_end = - walk_state->parser_state.pkg_end = method->data + method->length; + walk_state->parser_state.pkg_end = method->named.data + method->named.length; walk_state->parser_state.start_scope = op; walk_state->descending_callback = acpi_ds_load1_begin_op; walk_state->ascending_callback = acpi_ds_load1_end_op; + /* Perform the AML parse */ status = acpi_ps_parse_aml (walk_state); - - base_aml_offset = (method->value.arg)->aml_offset + 1; - start_op = (method->value.arg)->next; + base_aml_offset = (method->common.value.arg)->common.aml_offset + 1; + start_op = (method->common.value.arg)->common.next; search_op = start_op; while (search_op) { - search_op->aml_offset += base_aml_offset; + search_op->common.aml_offset += base_aml_offset; search_op = acpi_ps_get_depth_next (start_op, search_op); } - } - if (op->opcode == AML_REGION_OP) { + if (op->common.aml_opcode == AML_REGION_OP) { /* TBD: [Investigate] this isn't quite the right thing to do! */ /* * diff -Nru a/drivers/acpi/debugger/dbxface.c b/drivers/acpi/debugger/dbxface.c --- a/drivers/acpi/debugger/dbxface.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/debugger/dbxface.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dbxface - AML Debugger external interfaces - * $Revision: 55 $ + * $Revision: 59 $ * ******************************************************************************/ @@ -25,12 +25,7 @@ #include "acpi.h" -#include "acparser.h" #include "amlcode.h" -#include "acnamesp.h" -#include "acparser.h" -#include "acevents.h" -#include "acinterp.h" #include "acdebug.h" @@ -71,11 +66,12 @@ /* Check for single-step breakpoint */ - if (walk_state->method_breakpoint && (walk_state->method_breakpoint <= op->aml_offset)) { + if (walk_state->method_breakpoint && + (walk_state->method_breakpoint <= op->common.aml_offset)) { /* Check if the breakpoint has been reached or passed */ /* Hit the breakpoint, resume single step, reset breakpoint */ - acpi_os_printf ("***Break*** at AML offset %X\n", op->aml_offset); + acpi_os_printf ("***Break*** at AML offset %X\n", op->common.aml_offset); acpi_gbl_cm_single_step = TRUE; acpi_gbl_step_to_next_call = FALSE; walk_state->method_breakpoint = 0; @@ -83,8 +79,9 @@ /* Check for user breakpoint (Must be on exact Aml offset) */ - else if (walk_state->user_breakpoint && (walk_state->user_breakpoint == op->aml_offset)) { - acpi_os_printf ("***User_breakpoint*** at AML offset %X\n", op->aml_offset); + else if (walk_state->user_breakpoint && + (walk_state->user_breakpoint == op->common.aml_offset)) { + acpi_os_printf ("***User_breakpoint*** at AML offset %X\n", op->common.aml_offset); acpi_gbl_cm_single_step = TRUE; acpi_gbl_step_to_next_call = FALSE; walk_state->method_breakpoint = 0; @@ -95,7 +92,7 @@ * Check if this is an opcode that we are interested in -- * namely, opcodes that have arguments */ - if (op->opcode == AML_INT_NAMEDFIELD_OP) { + if (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { return (AE_OK); } @@ -103,6 +100,10 @@ case AML_CLASS_UNKNOWN: case AML_CLASS_ARGUMENT: /* constants, literals, etc. do nothing */ return (AE_OK); + + default: + /* All other opcodes -- continue */ + break; } /* @@ -123,12 +124,12 @@ */ original_debug_level = acpi_dbg_level; acpi_dbg_level &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS); - next = op->next; - op->next = NULL; + next = op->common.next; + op->common.next = NULL; display_op = op; - parent_op = op->parent; + parent_op = op->common.parent; if (parent_op) { if ((walk_state->control_state) && (walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING)) { @@ -138,25 +139,25 @@ * entire predicate can be displayed. */ while (parent_op) { - if ((parent_op->opcode == AML_IF_OP) || - (parent_op->opcode == AML_WHILE_OP)) { + if ((parent_op->common.aml_opcode == AML_IF_OP) || + (parent_op->common.aml_opcode == AML_WHILE_OP)) { display_op = parent_op; break; } - parent_op = parent_op->parent; + parent_op = parent_op->common.parent; } } else { while (parent_op) { - if ((parent_op->opcode == AML_IF_OP) || - (parent_op->opcode == AML_ELSE_OP) || - (parent_op->opcode == AML_SCOPE_OP) || - (parent_op->opcode == AML_METHOD_OP) || - (parent_op->opcode == AML_WHILE_OP)) { + if ((parent_op->common.aml_opcode == AML_IF_OP) || + (parent_op->common.aml_opcode == AML_ELSE_OP) || + (parent_op->common.aml_opcode == AML_SCOPE_OP) || + (parent_op->common.aml_opcode == AML_METHOD_OP) || + (parent_op->common.aml_opcode == AML_WHILE_OP)) { break; } display_op = parent_op; - parent_op = parent_op->parent; + parent_op = parent_op->common.parent; } } } @@ -165,8 +166,8 @@ acpi_db_display_op (walk_state, display_op, ACPI_UINT32_MAX); - if ((op->opcode == AML_IF_OP) || - (op->opcode == AML_WHILE_OP)) { + if ((op->common.aml_opcode == AML_IF_OP) || + (op->common.aml_opcode == AML_WHILE_OP)) { if (walk_state->control_state->common.value) { acpi_os_printf ("Predicate = [True], IF block was executed\n"); } @@ -175,13 +176,13 @@ } } - else if (op->opcode == AML_ELSE_OP) { + else if (op->common.aml_opcode == AML_ELSE_OP) { acpi_os_printf ("Predicate = [False], ELSE block was executed\n"); } /* Restore everything */ - op->next = next; + op->common.next = next; acpi_os_printf ("\n"); acpi_dbg_level = original_debug_level; } @@ -197,7 +198,7 @@ * Check if this is a method call. */ if (acpi_gbl_step_to_next_call) { - if (op->opcode != AML_INT_METHODCALL_OP) { + if (op->common.aml_opcode != AML_INT_METHODCALL_OP) { /* Not a method call, just keep executing */ return (AE_OK); @@ -212,7 +213,7 @@ * If the next opcode is a method call, we will "step over" it * by default. */ - if (op->opcode == AML_INT_METHODCALL_OP) { + if (op->common.aml_opcode == AML_INT_METHODCALL_OP) { acpi_gbl_cm_single_step = FALSE; /* No more single step while executing called method */ /* Set the breakpoint on/before the call, it will stop execution as soon as we return */ @@ -261,7 +262,7 @@ /* Get the user input line */ - acpi_os_get_line (acpi_gbl_db_line_buf); + (void) acpi_os_get_line (acpi_gbl_db_line_buf); } status = acpi_db_command_dispatch (acpi_gbl_db_line_buf, walk_state, op); @@ -287,9 +288,11 @@ * ******************************************************************************/ -int +acpi_status acpi_db_initialize (void) { + acpi_status status; + /* Init globals */ @@ -309,7 +312,7 @@ acpi_gbl_db_buffer = acpi_os_allocate (ACPI_DEBUG_BUFFER_SIZE); if (!acpi_gbl_db_buffer) { - return 0; + return (AE_NO_MEMORY); } ACPI_MEMSET (acpi_gbl_db_buffer, 0, ACPI_DEBUG_BUFFER_SIZE); @@ -327,12 +330,24 @@ if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) { /* These were created with one unit, grab it */ - acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); - acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_READY); + status = acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not get debugger mutex\n"); + return (status); + } + status = acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_READY); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not get debugger mutex\n"); + return (status); + } /* Create the debug execution thread to execute commands */ - acpi_os_queue_for_execution (0, acpi_db_execute_thread, NULL); + status = acpi_os_queue_for_execution (0, acpi_db_execute_thread, NULL); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not start debugger thread\n"); + return (status); + } } if (!acpi_gbl_db_opt_verbose) { @@ -341,7 +356,7 @@ acpi_gbl_db_opt_stats = FALSE; } - return (0); + return (AE_OK); } diff -Nru a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c --- a/drivers/acpi/dispatcher/dsfield.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/dispatcher/dsfield.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dsfield - Dispatcher field routines - * $Revision: 62 $ + * $Revision: 65 $ * *****************************************************************************/ @@ -74,7 +74,7 @@ /* Get the Name_string argument */ - if (op->opcode == AML_CREATE_FIELD_OP) { + if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { arg = acpi_ps_get_arg (op, 3); } else { @@ -102,7 +102,7 @@ /* * Enter the Name_string into the namespace */ - status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string, INTERNAL_TYPE_DEF_ANY, ACPI_IMODE_LOAD_PASS1, flags, walk_state, &(node)); if (ACPI_FAILURE (status)) { @@ -113,7 +113,7 @@ * for now, we will put it in the "op" object that the parser uses, so we * can get it again at the end of this scope */ - op->node = node; + op->common.node = node; /* * If there is no object attached to the node, this node was just created and @@ -144,8 +144,8 @@ * operands must be evaluated. */ second_desc = obj_desc->common.next_object; - second_desc->extra.aml_start = ((acpi_parse2_object *) op)->data; - second_desc->extra.aml_length = ((acpi_parse2_object *) op)->length; + second_desc->extra.aml_start = op->named.data; + second_desc->extra.aml_length = op->named.length; obj_desc->buffer_field.node = node; /* Attach constructed field descriptors to parent node */ @@ -187,6 +187,7 @@ acpi_parse_object *arg) { acpi_status status; + acpi_integer position; ACPI_FUNCTION_TRACE_PTR ("Ds_get_field_names", info); @@ -205,16 +206,18 @@ * 2) Access_as - changes the access mode * 3) Name - Enters a new named field into the namespace */ - switch (arg->opcode) { + switch (arg->common.aml_opcode) { case AML_INT_RESERVEDFIELD_OP: - if (((acpi_integer) info->field_bit_position + arg->value.size) > - ACPI_UINT32_MAX) { + position = (acpi_integer) info->field_bit_position + + (acpi_integer) arg->common.value.size; + + if (position > ACPI_UINT32_MAX) { ACPI_REPORT_ERROR (("Bit offset within field too large (> 0xFFFFFFFF)\n")); return_ACPI_STATUS (AE_SUPPORT); } - info->field_bit_position += arg->value.size; + info->field_bit_position = (u32) position; break; @@ -227,9 +230,9 @@ * In Field_flags, preserve the flag bits other than the ACCESS_TYPE bits */ info->field_flags = (u8) ((info->field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | - ((u8) (arg->value.integer32 >> 8))); + ((u8) (arg->common.value.integer32 >> 8))); - info->attribute = (u8) (arg->value.integer32); + info->attribute = (u8) (arg->common.value.integer32); break; @@ -238,7 +241,7 @@ /* Lookup the name */ status = acpi_ns_lookup (walk_state->scope_info, - (NATIVE_CHAR *) &((acpi_parse2_object *)arg)->name, + (NATIVE_CHAR *) &arg->named.name, info->field_type, ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE, walk_state, &info->field_node); if (ACPI_FAILURE (status)) { @@ -247,11 +250,11 @@ } ACPI_REPORT_ERROR (("Field name [%4.4s] already exists in current scope\n", - &((acpi_parse2_object *)arg)->name)); + &arg->named.name)); } else { - arg->node = info->field_node; - info->field_bit_length = arg->value.size; + arg->common.node = info->field_node; + info->field_bit_length = arg->common.value.size; /* Create and initialize an object for the new Field Node */ @@ -263,8 +266,10 @@ /* Keep track of bit position for the next field */ - if (((acpi_integer) info->field_bit_position + arg->value.size) > - ACPI_UINT32_MAX) { + position = (acpi_integer) info->field_bit_position + + (acpi_integer) arg->common.value.size; + + if (position > ACPI_UINT32_MAX) { ACPI_REPORT_ERROR (("Field [%4.4s] bit offset too large (> 0xFFFFFFFF)\n", &info->field_node->name)); return_ACPI_STATUS (AE_SUPPORT); @@ -277,11 +282,11 @@ default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid opcode in field list: %X\n", - arg->opcode)); - return_ACPI_STATUS (AE_AML_ERROR); + arg->common.aml_opcode)); + return_ACPI_STATUS (AE_AML_BAD_OPCODE); } - arg = arg->next; + arg = arg->common.next; } return_ACPI_STATUS (AE_OK); @@ -308,7 +313,7 @@ acpi_namespace_node *region_node, acpi_walk_state *walk_state) { - acpi_status status = AE_AML_ERROR; + acpi_status status; acpi_parse_object *arg; ACPI_CREATE_FIELD_INFO info; @@ -318,9 +323,9 @@ /* First arg is the name of the parent Op_region (must already exist) */ - arg = op->value.arg; + arg = op->common.value.arg; if (!region_node) { - status = acpi_ns_lookup (walk_state->scope_info, arg->value.name, + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name, ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, ®ion_node); if (ACPI_FAILURE (status)) { @@ -330,8 +335,8 @@ /* Second arg is the field flags */ - arg = arg->next; - info.field_flags = arg->value.integer8; + arg = arg->common.next; + info.field_flags = arg->common.value.integer8; info.attribute = 0; /* Each remaining arg is a Named Field */ @@ -339,7 +344,7 @@ info.field_type = INTERNAL_TYPE_REGION_FIELD; info.region_node = region_node; - status = acpi_ds_get_field_names (&info, walk_state, arg->next); + status = acpi_ds_get_field_names (&info, walk_state, arg->common.next); return_ACPI_STATUS (status); } @@ -365,7 +370,7 @@ acpi_parse_object *op, acpi_walk_state *walk_state) { - acpi_status status = AE_AML_ERROR; + acpi_status status; acpi_parse_object *arg = NULL; acpi_namespace_node *node; u8 type = 0; @@ -389,6 +394,9 @@ arg = acpi_ps_get_arg (op, 3); type = INTERNAL_TYPE_INDEX_FIELD; break; + + default: + return_ACPI_STATUS (AE_BAD_PARAMETER); } /* @@ -397,9 +405,9 @@ while (arg) { /* Ignore OFFSET and ACCESSAS terms here */ - if (arg->opcode == AML_INT_NAMEDFIELD_OP) { + if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { status = acpi_ns_lookup (walk_state->scope_info, - (NATIVE_CHAR *) &((acpi_parse2_object *)arg)->name, + (NATIVE_CHAR *) &arg->named.name, type, ACPI_IMODE_LOAD_PASS1, ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND, walk_state, &node); @@ -409,18 +417,22 @@ } ACPI_REPORT_ERROR (("Field name [%4.4s] already exists in current scope\n", - &((acpi_parse2_object *)arg)->name)); + &arg->named.name)); + + /* Name already exists, just ignore this error */ + + status = AE_OK; } - arg->node = node; + arg->common.node = node; } /* Move to next field in the list */ - arg = arg->next; + arg = arg->common.next; } - return_ACPI_STATUS (status); + return_ACPI_STATUS (AE_OK); } @@ -444,7 +456,7 @@ acpi_namespace_node *region_node, acpi_walk_state *walk_state) { - acpi_status status = AE_AML_ERROR; + acpi_status status; acpi_parse_object *arg; ACPI_CREATE_FIELD_INFO info; @@ -454,9 +466,9 @@ /* First arg is the name of the parent Op_region (must already exist) */ - arg = op->value.arg; + arg = op->common.value.arg; if (!region_node) { - status = acpi_ns_lookup (walk_state->scope_info, arg->value.name, + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name, ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, ®ion_node); if (ACPI_FAILURE (status)) { @@ -466,8 +478,8 @@ /* Second arg is the Bank Register (must already exist) */ - arg = arg->next; - status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + arg = arg->common.next; + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string, INTERNAL_TYPE_BANK_FIELD_DEFN, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node); if (ACPI_FAILURE (status)) { @@ -476,20 +488,20 @@ /* Third arg is the Bank_value */ - arg = arg->next; - info.bank_value = arg->value.integer32; + arg = arg->common.next; + info.bank_value = arg->common.value.integer32; /* Fourth arg is the field flags */ - arg = arg->next; - info.field_flags = arg->value.integer8; + arg = arg->common.next; + info.field_flags = arg->common.value.integer8; /* Each remaining arg is a Named Field */ info.field_type = INTERNAL_TYPE_BANK_FIELD; info.region_node = region_node; - status = acpi_ds_get_field_names (&info, walk_state, arg->next); + status = acpi_ds_get_field_names (&info, walk_state, arg->common.next); return_ACPI_STATUS (status); } @@ -525,8 +537,8 @@ /* First arg is the name of the Index register (must already exist) */ - arg = op->value.arg; - status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + arg = op->common.value.arg; + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node); if (ACPI_FAILURE (status)) { @@ -535,8 +547,8 @@ /* Second arg is the data register (must already exist) */ - arg = arg->next; - status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + arg = arg->common.next; + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string, INTERNAL_TYPE_INDEX_FIELD_DEFN, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &info.data_register_node); if (ACPI_FAILURE (status)) { @@ -545,8 +557,8 @@ /* Next arg is the field flags */ - arg = arg->next; - info.field_flags = arg->value.integer8; + arg = arg->common.next; + info.field_flags = arg->common.value.integer8; /* Each remaining arg is a Named Field */ @@ -554,7 +566,7 @@ info.field_type = INTERNAL_TYPE_INDEX_FIELD; info.region_node = region_node; - status = acpi_ds_get_field_names (&info, walk_state, arg->next); + status = acpi_ds_get_field_names (&info, walk_state, arg->common.next); return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c --- a/drivers/acpi/dispatcher/dsmethod.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/dispatcher/dsmethod.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dsmethod - Parser/Interpreter interface - control method parsing - * $Revision: 81 $ + * $Revision: 86 $ * *****************************************************************************/ @@ -30,8 +30,6 @@ #include "acdispat.h" #include "acinterp.h" #include "acnamesp.h" -#include "actables.h" -#include "acdebug.h" #define _COMPONENT ACPI_DISPATCHER @@ -78,7 +76,7 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** Named_obj=%p\n", - (char *) &((acpi_namespace_node *) obj_handle)->name, obj_handle)); + ((acpi_namespace_node *) obj_handle)->name.ascii, obj_handle)); /* Extract the method object from the method Node */ @@ -112,7 +110,7 @@ /* Init new op with the method name and pointer back to the Node */ acpi_ps_set_name (op, node->name.integer); - op->node = node; + op->common.node = node; /* * Get a new Owner_id for objects created by this method. Namespace @@ -124,8 +122,7 @@ /* Create and initialize a new walk state */ - walk_state = acpi_ds_create_walk_state (owner_id, - NULL, NULL, NULL); + walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } @@ -152,8 +149,9 @@ return_ACPI_STATUS (status); } - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** [%4.4s] Parsed **** Named_obj=%p Op=%p\n", - (char *) &((acpi_namespace_node *) obj_handle)->name, obj_handle, op)); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "**** [%4.4s] Parsed **** Named_obj=%p Op=%p\n", + ((acpi_namespace_node *) obj_handle)->name.ascii, obj_handle, op)); acpi_ps_delete_parse_tree (op); return_ACPI_STATUS (status); @@ -348,8 +346,8 @@ this_walk_state->num_operands = 0; - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Starting nested execution, newstate=%p\n", - next_walk_state)); + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Starting nested execution, newstate=%p\n", next_walk_state)); return_ACPI_STATUS (AE_OK); @@ -357,7 +355,7 @@ /* On error, we must delete the new walk state */ cleanup: - acpi_ds_terminate_control_method (next_walk_state); + (void) acpi_ds_terminate_control_method (next_walk_state); acpi_ds_delete_walk_state (next_walk_state); return_ACPI_STATUS (status); @@ -444,6 +442,10 @@ ACPI_FUNCTION_TRACE_PTR ("Ds_terminate_control_method", walk_state); + if (!walk_state) { + return (AE_BAD_PARAMETER); + } + /* The current method object was saved in the walk state */ obj_desc = walk_state->method_desc; @@ -468,8 +470,14 @@ /* Signal completion of the execution of this method if necessary */ if (walk_state->method_desc->method.semaphore) { - acpi_os_signal_semaphore ( - walk_state->method_desc->method.semaphore, 1); + status = acpi_os_signal_semaphore ( + walk_state->method_desc->method.semaphore, 1); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not signal method semaphore\n")); + status = AE_OK; + + /* Ignore error and continue cleanup */ + } } /* Decrement the thread count on the method parse tree */ diff -Nru a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c --- a/drivers/acpi/dispatcher/dsmthdat.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/dispatcher/dsmthdat.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dsmthdat - control method arguments and local variables - * $Revision: 59 $ + * $Revision: 61 $ * ******************************************************************************/ @@ -25,9 +25,7 @@ #include "acpi.h" -#include "acparser.h" #include "acdispat.h" -#include "acinterp.h" #include "amlcode.h" #include "acnamesp.h" @@ -57,7 +55,7 @@ * ******************************************************************************/ -acpi_status +void acpi_ds_method_data_init ( acpi_walk_state *walk_state) { @@ -90,7 +88,7 @@ walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL; } - return_ACPI_STATUS (AE_OK); + return_VOID; } @@ -100,14 +98,14 @@ * * PARAMETERS: Walk_state - Current walk state object * - * RETURN: Status + * RETURN: None * * DESCRIPTION: Delete method locals and arguments. Arguments are only * deleted if this method was called from another method. * ******************************************************************************/ -acpi_status +void acpi_ds_method_data_delete_all ( acpi_walk_state *walk_state) { @@ -127,7 +125,7 @@ /* Detach object (if present) and remove a reference */ acpi_ns_detach_object (&walk_state->local_variables[index]); - } + } } /* Detach the arguments */ @@ -143,7 +141,7 @@ } } - return_ACPI_STATUS (AE_OK); + return_VOID; } @@ -435,6 +433,9 @@ index, node)); return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL); + + default: + return_ACPI_STATUS (AE_AML_INTERNAL); } } @@ -457,14 +458,14 @@ * Index - Which local_var or argument to delete * Walk_state - Current walk state object * - * RETURN: Status + * RETURN: None * * DESCRIPTION: Delete the entry at Opcode:Index on the method stack. Inserts * a null into the stack slot after the object is deleted. * ******************************************************************************/ -acpi_status +void acpi_ds_method_data_delete_value ( u16 opcode, u32 index, @@ -482,7 +483,7 @@ status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + return_VOID; } /* Get the associated object */ @@ -497,7 +498,7 @@ node->object = NULL; if ((object) && - (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_INTERNAL)) { + (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_OPERAND)) { /* * There is a valid object. * Decrement the reference count by one to balance the @@ -506,7 +507,7 @@ acpi_ut_remove_reference (object); } - return_ACPI_STATUS (AE_OK); + return_VOID; } diff -Nru a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c --- a/drivers/acpi/dispatcher/dsobject.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/dispatcher/dsobject.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dsobject - Dispatcher object management routines - * $Revision: 91 $ + * $Revision: 99 $ * *****************************************************************************/ @@ -28,7 +28,6 @@ #include "acparser.h" #include "amlcode.h" #include "acdispat.h" -#include "acinterp.h" #include "acnamesp.h" #define _COMPONENT ACPI_DISPATCHER @@ -65,15 +64,11 @@ acpi_object_type type; acpi_status status; acpi_init_walk_info *info = (acpi_init_walk_info *) context; - u8 table_revision; ACPI_FUNCTION_NAME ("Ds_init_one_object"); - info->object_count++; - table_revision = info->table_desc->pointer->revision; - /* * We are only interested in objects owned by the table that * was just loaded @@ -83,6 +78,8 @@ return (AE_OK); } + info->object_count++; + /* And even then, we are only interested in a few object types */ type = acpi_ns_get_type (obj_handle); @@ -90,7 +87,12 @@ switch (type) { case ACPI_TYPE_REGION: - acpi_ds_initialize_region (obj_handle); + status = acpi_ds_initialize_region (obj_handle); + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %p [%4.4s] - Init failure, %s\n", + obj_handle, ((acpi_namespace_node *) obj_handle)->name.ascii, + acpi_format_exception (status))); + } info->op_region_count++; break; @@ -107,9 +109,11 @@ /* * Set the execution data width (32 or 64) based upon the * revision number of the parent ACPI table. + * TBD: This is really for possible future support of integer width + * on a per-table basis. Currently, we just use a global for the width. */ - if (table_revision == 1) { - ((acpi_namespace_node *)obj_handle)->flags |= ANOBJ_DATA_WIDTH_32; + if (info->table_desc->pointer->revision == 1) { + ((acpi_namespace_node *) obj_handle)->flags |= ANOBJ_DATA_WIDTH_32; } /* @@ -119,7 +123,7 @@ status = acpi_ds_parse_method (obj_handle); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Method %p [%4.4s] - parse failure, %s\n", - obj_handle, (char *) &((acpi_namespace_node *) obj_handle)->name, + obj_handle, ((acpi_namespace_node *) obj_handle)->name.ascii, acpi_format_exception (status))); /* This parse failed, but we will continue parsing more methods */ @@ -135,6 +139,13 @@ acpi_ns_delete_namespace_by_owner (((acpi_namespace_node *) obj_handle)->object->method.owning_id); break; + + case ACPI_TYPE_DEVICE: + + info->device_count++; + break; + + default: break; } @@ -177,10 +188,10 @@ "**** Starting initialization of namespace objects ****\n")); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "Parsing Methods:")); - info.method_count = 0; info.op_region_count = 0; info.object_count = 0; + info.device_count = 0; info.table_desc = table_desc; /* Walk entire namespace from the supplied root */ @@ -188,16 +199,17 @@ status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, acpi_ds_init_one_object, &info, NULL); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed! %x\n", status)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed, %s\n", + acpi_format_exception (status))); } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, - "\n%d Control Methods found and parsed (%d nodes total)\n", - info.method_count, info.object_count)); - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "%d Control Methods found\n", info.method_count)); + "\nTable [%4.4s] - %hd Objects with %hd Devices %hd Methods %hd Regions\n", + table_desc->pointer->signature, info.object_count, + info.device_count, info.method_count, info.op_region_count)); + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "%d Op Regions found\n", info.op_region_count)); + "%hd Methods, %hd Regions\n", info.method_count, info.op_region_count)); return_ACPI_STATUS (AE_OK); } @@ -251,8 +263,8 @@ * Defer evaluation of Buffer Term_arg operand */ obj_desc->buffer.node = (acpi_namespace_node *) walk_state->operands[0]; - obj_desc->buffer.aml_start = ((acpi_parse2_object *) op)->data; - obj_desc->buffer.aml_length = ((acpi_parse2_object *) op)->length; + obj_desc->buffer.aml_start = op->named.data; + obj_desc->buffer.aml_length = op->named.length; break; @@ -262,21 +274,21 @@ * Defer evaluation of Package Term_arg operand */ obj_desc->package.node = (acpi_namespace_node *) walk_state->operands[0]; - obj_desc->package.aml_start = ((acpi_parse2_object *) op)->data; - obj_desc->package.aml_length = ((acpi_parse2_object *) op)->length; + obj_desc->package.aml_start = op->named.data; + obj_desc->package.aml_length = op->named.length; break; case ACPI_TYPE_INTEGER: - obj_desc->integer.value = op->value.integer; + obj_desc->integer.value = op->common.value.integer; break; case ACPI_TYPE_STRING: - obj_desc->string.pointer = op->value.string; - obj_desc->string.length = ACPI_STRLEN (op->value.string); + obj_desc->string.pointer = op->common.value.string; + obj_desc->string.length = ACPI_STRLEN (op->common.value.string); /* * The string is contained in the ACPI table, don't ever try @@ -313,10 +325,10 @@ default: /* Constants, Literals, etc.. */ - if (op->opcode == AML_INT_NAMEPATH_OP) { + if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { /* Node was saved in Op */ - obj_desc->reference.node = op->node; + obj_desc->reference.node = op->common.node; } obj_desc->reference.opcode = opcode; @@ -327,7 +339,7 @@ default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %x\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n", obj_desc->common.type)); break; @@ -366,31 +378,30 @@ ACPI_FUNCTION_TRACE ("Ds_build_internal_object"); - if (op->opcode == AML_INT_NAMEPATH_OP) { + if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { /* * This is an object reference. If this name was * previously looked up in the namespace, it was stored in this op. * Otherwise, go ahead and look it up now */ - if (!op->node) { - status = acpi_ns_lookup (walk_state->scope_info, op->value.string, + if (!op->common.node) { + status = acpi_ns_lookup (walk_state->scope_info, op->common.value.string, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, - (acpi_namespace_node **) &(op->node)); + (acpi_namespace_node **) &(op->common.node)); if (ACPI_FAILURE (status)) { if (status == AE_NOT_FOUND) { name = NULL; - acpi_ns_externalize_name (ACPI_UINT32_MAX, op->value.string, NULL, &name); - - if (name) { + status = acpi_ns_externalize_name (ACPI_UINT32_MAX, op->common.value.string, NULL, &name); + if (ACPI_SUCCESS (status)) { ACPI_REPORT_WARNING (("Reference %s at AML %X not found\n", - name, op->aml_offset)); + name, op->common.aml_offset)); ACPI_MEM_FREE (name); } else { ACPI_REPORT_WARNING (("Reference %s at AML %X not found\n", - op->value.string, op->aml_offset)); + op->common.value.string, op->common.aml_offset)); } *obj_desc_ptr = NULL; @@ -404,12 +415,12 @@ /* Create and init the internal ACPI object */ - obj_desc = acpi_ut_create_internal_object ((acpi_ps_get_opcode_info (op->opcode))->object_type); + obj_desc = acpi_ut_create_internal_object ((acpi_ps_get_opcode_info (op->common.aml_opcode))->object_type); if (!obj_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } - status = acpi_ds_init_object_from_op (walk_state, op, op->opcode, &obj_desc); + status = acpi_ds_init_object_from_op (walk_state, op, op->common.aml_opcode, &obj_desc); if (ACPI_FAILURE (status)) { acpi_ut_remove_reference (obj_desc); return_ACPI_STATUS (status); @@ -443,7 +454,7 @@ { acpi_parse_object *arg; acpi_operand_object *obj_desc; - acpi_parse2_object *byte_list; + acpi_parse_object *byte_list; u32 byte_list_length = 0; @@ -472,20 +483,20 @@ * individual bytes or a string initializer. In either case, a * Byte_list appears in the AML. */ - arg = op->value.arg; /* skip first arg */ + arg = op->common.value.arg; /* skip first arg */ - byte_list = (acpi_parse2_object *) arg->next; + byte_list = arg->named.next; if (byte_list) { - if (byte_list->opcode != AML_INT_BYTELIST_OP) { + if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Expecting bytelist, got AML opcode %X in op %p\n", - byte_list->opcode, byte_list)); + byte_list->common.aml_opcode, byte_list)); acpi_ut_remove_reference (obj_desc); return (AE_TYPE); } - byte_list_length = byte_list->value.integer32; + byte_list_length = byte_list->common.value.integer32; } /* @@ -516,12 +527,12 @@ /* Initialize buffer from the Byte_list (if present) */ if (byte_list) { - ACPI_MEMCPY (obj_desc->buffer.pointer, byte_list->data, + ACPI_MEMCPY (obj_desc->buffer.pointer, byte_list->named.data, byte_list_length); } obj_desc->buffer.flags |= AOPOBJ_DATA_VALID; - op->node = (acpi_namespace_node *) obj_desc; + op->common.node = (acpi_namespace_node *) obj_desc; return_ACPI_STATUS (AE_OK); } @@ -560,11 +571,10 @@ /* Find the parent of a possibly nested package */ - - parent = op->parent; - while ((parent->opcode == AML_PACKAGE_OP) || - (parent->opcode == AML_VAR_PACKAGE_OP)) { - parent = parent->parent; + parent = op->common.parent; + while ((parent->common.aml_opcode == AML_PACKAGE_OP) || + (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { + parent = parent->common.parent; } obj_desc = *obj_desc_ptr; @@ -581,7 +591,7 @@ return_ACPI_STATUS (AE_NO_MEMORY); } - obj_desc->package.node = parent->node; + obj_desc->package.node = parent->common.node; } obj_desc->package.count = package_length; @@ -589,11 +599,11 @@ /* Count the number of items in the package list */ package_list_length = 0; - arg = op->value.arg; - arg = arg->next; + arg = op->common.value.arg; + arg = arg->common.next; while (arg) { package_list_length++; - arg = arg->next; + arg = arg->common.next; } /* @@ -610,7 +620,7 @@ * that the list is always null terminated. */ obj_desc->package.elements = ACPI_MEM_CALLOCATE ( - (obj_desc->package.count + 1) * sizeof (void *)); + ((ACPI_SIZE) obj_desc->package.count + 1) * sizeof (void *)); if (!obj_desc->package.elements) { acpi_ut_delete_object_desc (obj_desc); @@ -621,13 +631,13 @@ * Now init the elements of the package */ i = 0; - arg = op->value.arg; - arg = arg->next; + arg = op->common.value.arg; + arg = arg->common.next; while (arg) { - if (arg->opcode == AML_INT_RETURN_VALUE_OP) { + if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { /* Object (package or buffer) is already built */ - obj_desc->package.elements[i] = (acpi_operand_object *) arg->node; + obj_desc->package.elements[i] = ACPI_CAST_PTR (acpi_operand_object, arg->common.node); } else { status = acpi_ds_build_internal_object (walk_state, arg, @@ -635,11 +645,11 @@ } i++; - arg = arg->next; + arg = arg->common.next; } obj_desc->package.flags |= AOPOBJ_DATA_VALID; - op->node = (acpi_namespace_node *) obj_desc; + op->common.node = (acpi_namespace_node *) obj_desc; return_ACPI_STATUS (status); } @@ -679,7 +689,7 @@ return_ACPI_STATUS (AE_OK); } - if (!op->value.arg) { + if (!op->common.value.arg) { /* No arguments, there is nothing to do */ return_ACPI_STATUS (AE_OK); @@ -687,7 +697,7 @@ /* Build an internal object for the argument(s) */ - status = acpi_ds_build_internal_object (walk_state, op->value.arg, &obj_desc); + status = acpi_ds_build_internal_object (walk_state, op->common.value.arg, &obj_desc); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c --- a/drivers/acpi/dispatcher/dsopcode.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/dispatcher/dsopcode.c Sun Jun 2 18:44:57 2002 @@ -2,7 +2,7 @@ * * Module Name: dsopcode - Dispatcher Op Region support and handling of * "control" opcodes - * $Revision: 74 $ + * $Revision: 79 $ * *****************************************************************************/ @@ -32,7 +32,6 @@ #include "acinterp.h" #include "acnamesp.h" #include "acevents.h" -#include "actables.h" #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME ("dsopcode") @@ -43,7 +42,8 @@ * FUNCTION: Acpi_ds_execute_arguments * * PARAMETERS: Node - Parent NS node - * Extra_desc - Has AML pointer and length + * Aml_length - Length of executable AML + * Aml_start - Pointer to the AML * * RETURN: Status. * @@ -77,7 +77,7 @@ /* Save the Node for use in Acpi_ps_parse_aml */ - op->node = scope_node; + op->common.node = scope_node; /* Create and initialize a new parser state */ @@ -105,9 +105,9 @@ /* Get and init the Op created above */ - arg = op->value.arg; - op->node = node; - arg->node = node; + arg = op->common.value.arg; + op->common.node = node; + arg->common.node = node; acpi_ps_delete_parse_tree (op); /* Evaluate the address and length arguments for the Buffer Field */ @@ -117,7 +117,7 @@ return_ACPI_STATUS (AE_NO_MEMORY); } - op->node = scope_node; + op->common.node = scope_node; /* Create and initialize a new parser state */ @@ -175,7 +175,7 @@ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (node, " [Field]")); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] Buffer_field JIT Init\n", - (char *) &node->name)); + node->name.ascii)); /* Execute the AML code for the Term_arg arguments */ @@ -320,7 +320,7 @@ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (node, " [Operation Region]")); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] Op_region Init at AML %p\n", - (char *) &node->name, extra_desc->extra.aml_start)); + node->name.ascii, extra_desc->extra.aml_start)); status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node), @@ -337,7 +337,7 @@ * * RETURN: Status * - * DESCRIPTION: + * DESCRIPTION: Front end to Ev_initialize_region * ****************************************************************************/ @@ -360,110 +360,76 @@ /***************************************************************************** * - * FUNCTION: Acpi_ds_eval_buffer_field_operands + * FUNCTION: Acpi_ds_init_buffer_field * - * PARAMETERS: Op - A valid Buffer_field Op object + * PARAMETERS: Aml_opcode - Create_xxx_field + * Obj_desc - Buffer_field object + * Buffer_desc - Host Buffer + * Offset_desc - Offset into buffer + * Length - Length of field (CREATE_FIELD_OP only) + * Result - Where to store the result * * RETURN: Status * - * DESCRIPTION: Get Buffer_field Buffer and Index - * Called from Acpi_ds_exec_end_op during Buffer_field parse tree walk + * DESCRIPTION: Perform actual initialization of a buffer field * ****************************************************************************/ acpi_status -acpi_ds_eval_buffer_field_operands ( - acpi_walk_state *walk_state, - acpi_parse_object *op) +acpi_ds_init_buffer_field ( + u16 aml_opcode, + acpi_operand_object *obj_desc, + acpi_operand_object *buffer_desc, + acpi_operand_object *offset_desc, + acpi_operand_object *length_desc, + acpi_operand_object *result_desc) { - acpi_status status; - acpi_operand_object *obj_desc; - acpi_namespace_node *node; - acpi_parse_object *next_op; u32 offset; u32 bit_offset; u32 bit_count; u8 field_flags; - acpi_operand_object *res_desc = NULL; - acpi_operand_object *cnt_desc = NULL; - acpi_operand_object *off_desc = NULL; - acpi_operand_object *src_desc = NULL; - - - ACPI_FUNCTION_TRACE_PTR ("Ds_eval_buffer_field_operands", op); - - - /* - * This is where we evaluate the address and length fields of the - * Create_xxx_field declaration - */ - node = op->node; - - /* Next_op points to the op that holds the Buffer */ + acpi_status status; - next_op = op->value.arg; - /* Evaluate/create the address and length operands */ + ACPI_FUNCTION_TRACE_PTR ("Ds_init_buffer_field", obj_desc); - status = acpi_ds_create_operands (walk_state, next_op); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - obj_desc = acpi_ns_get_attached_object (node); - if (!obj_desc) { - return_ACPI_STATUS (AE_NOT_EXIST); - } - - /* Resolve the operands */ - - status = acpi_ex_resolve_operands (op->opcode, ACPI_WALK_OPERANDS, walk_state); - ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, acpi_ps_get_opcode_name (op->opcode), - walk_state->num_operands, "after Acpi_ex_resolve_operands"); + /* Host object must be a Buffer */ - if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)\n", - acpi_ps_get_opcode_name (op->opcode), status)); + if (buffer_desc->common.type != ACPI_TYPE_BUFFER) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Target of Create Field is not a Buffer object - %s\n", + acpi_ut_get_type_name (buffer_desc->common.type))); + status = AE_AML_OPERAND_TYPE; goto cleanup; } - /* Get the operands */ - - if (AML_CREATE_FIELD_OP == op->opcode) { - res_desc = walk_state->operands[3]; - cnt_desc = walk_state->operands[2]; - } - else { - res_desc = walk_state->operands[2]; - } - - off_desc = walk_state->operands[1]; - src_desc = walk_state->operands[0]; - offset = (u32) off_desc->integer.value; - /* - * If Res_desc is a Name, it will be a direct name pointer after - * Acpi_ex_resolve_operands() + * The last parameter to all of these opcodes (Result_desc) started + * out as a Name_string, and should therefore now be a NS node + * after resolution in Acpi_ex_resolve_operands(). */ - if (ACPI_GET_DESCRIPTOR_TYPE (res_desc) != ACPI_DESC_TYPE_NAMED) { + if (ACPI_GET_DESCRIPTOR_TYPE (result_desc) != ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) destination must be a NS Node\n", - acpi_ps_get_opcode_name (op->opcode))); + acpi_ps_get_opcode_name (aml_opcode))); status = AE_AML_OPERAND_TYPE; goto cleanup; } + offset = (u32) offset_desc->integer.value; + /* * Setup the Bit offsets and counts, according to the opcode */ - switch (op->opcode) { + switch (aml_opcode) { case AML_CREATE_FIELD_OP: /* Offset is in bits, count is in bits */ - bit_offset = offset; - bit_count = (u32) cnt_desc->integer.value; + bit_offset = offset; + bit_count = (u32) length_desc->integer.value; field_flags = AML_FIELD_ACCESS_BYTE; break; @@ -471,8 +437,8 @@ /* Offset is in bits, Field is one bit */ - bit_offset = offset; - bit_count = 1; + bit_offset = offset; + bit_count = 1; field_flags = AML_FIELD_ACCESS_BYTE; break; @@ -480,8 +446,8 @@ /* Offset is in bytes, field is one byte */ - bit_offset = 8 * offset; - bit_count = 8; + bit_offset = 8 * offset; + bit_count = 8; field_flags = AML_FIELD_ACCESS_BYTE; break; @@ -489,8 +455,8 @@ /* Offset is in bytes, field is one word */ - bit_offset = 8 * offset; - bit_count = 16; + bit_offset = 8 * offset; + bit_count = 16; field_flags = AML_FIELD_ACCESS_WORD; break; @@ -498,8 +464,8 @@ /* Offset is in bytes, field is one dword */ - bit_offset = 8 * offset; - bit_count = 32; + bit_offset = 8 * offset; + bit_count = 32; field_flags = AML_FIELD_ACCESS_DWORD; break; @@ -507,105 +473,157 @@ /* Offset is in bytes, field is one qword */ - bit_offset = 8 * offset; - bit_count = 64; + bit_offset = 8 * offset; + bit_count = 64; field_flags = AML_FIELD_ACCESS_QWORD; break; default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Internal error - unknown field creation opcode %02x\n", - op->opcode)); + "Unknown field creation opcode %02x\n", + aml_opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } + + /* Entire field must fit within the current length of the buffer */ + + if ((bit_offset + bit_count) > + (8 * (u32) buffer_desc->buffer.length)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Field size %d exceeds Buffer size %d (bits)\n", + bit_offset + bit_count, 8 * (u32) buffer_desc->buffer.length)); + status = AE_AML_BUFFER_LIMIT; + goto cleanup; + } + /* - * Setup field according to the object type + * Initialize areas of the field object that are common to all fields + * For Field_flags, use LOCK_RULE = 0 (NO_LOCK), UPDATE_RULE = 0 (UPDATE_PRESERVE) */ - switch (src_desc->common.type) { - - /* Source_buff := Term_arg=>Buffer */ + status = acpi_ex_prep_common_field_object (obj_desc, field_flags, 0, + bit_offset, bit_count); + if (ACPI_FAILURE (status)) { + goto cleanup; + } - case ACPI_TYPE_BUFFER: + obj_desc->buffer_field.buffer_obj = buffer_desc; - if ((bit_offset + bit_count) > - (8 * (u32) src_desc->buffer.length)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Field size %d exceeds Buffer size %d (bits)\n", - bit_offset + bit_count, 8 * (u32) src_desc->buffer.length)); - status = AE_AML_BUFFER_LIMIT; - goto cleanup; - } + /* Reference count for Buffer_desc inherits Obj_desc count */ - /* - * Initialize areas of the field object that are common to all fields - * For Field_flags, use LOCK_RULE = 0 (NO_LOCK), UPDATE_RULE = 0 (UPDATE_PRESERVE) - */ - status = acpi_ex_prep_common_field_object (obj_desc, field_flags, 0, - bit_offset, bit_count); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + buffer_desc->common.reference_count = (u16) (buffer_desc->common.reference_count + + obj_desc->common.reference_count); - obj_desc->buffer_field.buffer_obj = src_desc; - /* Reference count for Src_desc inherits Obj_desc count */ +cleanup: - src_desc->common.reference_count = (u16) (src_desc->common.reference_count + - obj_desc->common.reference_count); - break; + /* Always delete the operands */ + acpi_ut_remove_reference (offset_desc); + acpi_ut_remove_reference (buffer_desc); - /* Improper object type */ + if (aml_opcode == AML_CREATE_FIELD_OP) { + acpi_ut_remove_reference (length_desc); + } - default: + /* On failure, delete the result descriptor */ - if ((src_desc->common.type > (u8) INTERNAL_TYPE_REFERENCE) || !acpi_ut_valid_object_type (src_desc->common.type)) /* This line MUST be a single line until Acpi_src can handle it (block deletion) */ { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Tried to create field in invalid object type %X\n", - src_desc->common.type)); - } - else { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Tried to create field in improper object type - %s\n", - acpi_ut_get_type_name (src_desc->common.type))); - } + if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (result_desc); /* Result descriptor */ + } + else { + /* Now the address and length are valid for this Buffer_field */ - status = AE_AML_OPERAND_TYPE; - goto cleanup; + obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID; } + return_ACPI_STATUS (status); +} - if (AML_CREATE_FIELD_OP == op->opcode) { - /* Delete object descriptor unique to Create_field */ - acpi_ut_remove_reference (cnt_desc); - cnt_desc = NULL; - } +/***************************************************************************** + * + * FUNCTION: Acpi_ds_eval_buffer_field_operands + * + * PARAMETERS: Walk_state - Current walk + * Op - A valid Buffer_field Op object + * + * RETURN: Status + * + * DESCRIPTION: Get Buffer_field Buffer and Index + * Called from Acpi_ds_exec_end_op during Buffer_field parse tree walk + * + ****************************************************************************/ +acpi_status +acpi_ds_eval_buffer_field_operands ( + acpi_walk_state *walk_state, + acpi_parse_object *op) +{ + acpi_status status; + acpi_operand_object *obj_desc; + acpi_namespace_node *node; + acpi_parse_object *next_op; -cleanup: - /* Always delete the operands */ + ACPI_FUNCTION_TRACE_PTR ("Ds_eval_buffer_field_operands", op); + + + /* + * This is where we evaluate the address and length fields of the + * Create_xxx_field declaration + */ + node = op->common.node; + + /* Next_op points to the op that holds the Buffer */ - acpi_ut_remove_reference (off_desc); - acpi_ut_remove_reference (src_desc); + next_op = op->common.value.arg; + + /* Evaluate/create the address and length operands */ + + status = acpi_ds_create_operands (walk_state, next_op); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - if (AML_CREATE_FIELD_OP == op->opcode) { - acpi_ut_remove_reference (cnt_desc); + obj_desc = acpi_ns_get_attached_object (node); + if (!obj_desc) { + return_ACPI_STATUS (AE_NOT_EXIST); } - /* On failure, delete the result descriptor */ + /* Resolve the operands */ + + status = acpi_ex_resolve_operands (op->common.aml_opcode, + ACPI_WALK_OPERANDS, walk_state); + + ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, + acpi_ps_get_opcode_name (op->common.aml_opcode), + walk_state->num_operands, "after Acpi_ex_resolve_operands"); if (ACPI_FAILURE (status)) { - acpi_ut_remove_reference (res_desc); /* Result descriptor */ + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)\n", + acpi_ps_get_opcode_name (op->common.aml_opcode), status)); + + return_ACPI_STATUS (status); + } + + /* Initialize the Buffer Field */ + + if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { + /* NOTE: Slightly different operands for this opcode */ + + status = acpi_ds_init_buffer_field (op->common.aml_opcode, obj_desc, + walk_state->operands[0], walk_state->operands[1], + walk_state->operands[2], walk_state->operands[3]); } else { - /* Now the address and length are valid for this Buffer_field */ + /* All other, Create_xxx_field opcodes */ - obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID; + status = acpi_ds_init_buffer_field (op->common.aml_opcode, obj_desc, + walk_state->operands[0], walk_state->operands[1], + NULL, walk_state->operands[2]); } return_ACPI_STATUS (status); @@ -616,7 +634,8 @@ * * FUNCTION: Acpi_ds_eval_region_operands * - * PARAMETERS: Op - A valid region Op object + * PARAMETERS: Walk_state - Current walk + * Op - A valid region Op object * * RETURN: Status * @@ -643,15 +662,15 @@ /* * This is where we evaluate the address and length fields of the Op_region declaration */ - node = op->node; + node = op->common.node; /* Next_op points to the op that holds the Space_iD */ - next_op = op->value.arg; + next_op = op->common.value.arg; /* Next_op points to address op */ - next_op = next_op->next; + next_op = next_op->common.next; /* Evaluate/create the address and length operands */ @@ -662,13 +681,13 @@ /* Resolve the length and address operands to numbers */ - status = acpi_ex_resolve_operands (op->opcode, ACPI_WALK_OPERANDS, walk_state); + status = acpi_ex_resolve_operands (op->common.aml_opcode, ACPI_WALK_OPERANDS, walk_state); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, - acpi_ps_get_opcode_name (op->opcode), + acpi_ps_get_opcode_name (op->common.aml_opcode), 1, "after Acpi_ex_resolve_operands"); obj_desc = acpi_ns_get_attached_object (node); @@ -711,7 +730,9 @@ * * FUNCTION: Acpi_ds_eval_data_object_operands * - * PARAMETERS: Op - A valid Data_object Op object + * PARAMETERS: Walk_state - Current walk + * Op - A valid Data_object Op object + * Obj_desc - Data_object * * RETURN: Status * @@ -737,7 +758,7 @@ /* The first operand (for all of these data objects) is the length */ - status = acpi_ds_create_operand (walk_state, op->value.arg, 1); + status = acpi_ds_create_operand (walk_state, op->common.value.arg, 1); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -756,13 +777,17 @@ /* Cleanup for length operand */ - acpi_ds_obj_stack_pop (1, walk_state); + status = acpi_ds_obj_stack_pop (1, walk_state); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + acpi_ut_remove_reference (arg_desc); /* * Create the actual data object */ - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_BUFFER_OP: status = acpi_ds_build_internal_buffer_obj (walk_state, op, length, &obj_desc); @@ -784,10 +809,10 @@ * in this case, the return object will be stored in the parse tree * for the package. */ - if ((!op->parent) || - ((op->parent->opcode != AML_PACKAGE_OP) && - (op->parent->opcode != AML_VAR_PACKAGE_OP) && - (op->parent->opcode != AML_NAME_OP))) { + if ((!op->common.parent) || + ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && + (op->common.parent->common.aml_opcode != AML_VAR_PACKAGE_OP) && + (op->common.parent->common.aml_opcode != AML_NAME_OP))) { walk_state->result_obj = obj_desc; } } @@ -823,9 +848,9 @@ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op, - op->opcode, walk_state)); + op->common.aml_opcode, walk_state)); - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_IF_OP: case AML_WHILE_OP: @@ -845,7 +870,7 @@ */ control_state->control.aml_predicate_start = walk_state->parser_state.aml - 1; control_state->control.package_end = walk_state->parser_state.pkg_end; - control_state->control.opcode = op->opcode; + control_state->control.opcode = op->common.aml_opcode; /* Push the control state on this walk's control stack */ @@ -902,7 +927,7 @@ ACPI_FUNCTION_NAME ("Ds_exec_end_control_op"); - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_IF_OP: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); @@ -952,17 +977,17 @@ case AML_RETURN_OP: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "[RETURN_OP] Op=%p Arg=%p\n",op, op->value.arg)); + "[RETURN_OP] Op=%p Arg=%p\n",op, op->common.value.arg)); /* * One optional operand -- the return value * It can be either an immediate operand or a result that * has been bubbled up the tree */ - if (op->value.arg) { + if (op->common.value.arg) { /* Return statement has an immediate operand */ - status = acpi_ds_create_operands (walk_state, op->value.arg); + status = acpi_ds_create_operands (walk_state, op->common.value.arg); if (ACPI_FAILURE (status)) { return (status); } @@ -995,7 +1020,7 @@ * * Allow references created by the Index operator to return unchanged. */ - if ((ACPI_GET_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc[0]) == ACPI_DESC_TYPE_INTERNAL) && + if ((ACPI_GET_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc[0]) == ACPI_DESC_TYPE_OPERAND) && ((walk_state->results->results.obj_desc [0])->common.type == INTERNAL_TYPE_REFERENCE) && ((walk_state->results->results.obj_desc [0])->reference.opcode != AML_INDEX_OP)) { status = acpi_ex_resolve_to_value (&walk_state->results->results.obj_desc [0], walk_state); @@ -1039,7 +1064,7 @@ /* Call up to the OS service layer to handle this */ - acpi_os_signal (ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode"); + status = acpi_os_signal (ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode"); /* If and when it returns, all done. */ @@ -1070,7 +1095,7 @@ /* Return status depending on opcode */ - if (op->opcode == AML_BREAK_OP) { + if (op->common.aml_opcode == AML_BREAK_OP) { status = AE_CTRL_BREAK; } else { @@ -1082,7 +1107,7 @@ default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown control opcode=%X Op=%p\n", - op->opcode, op)); + op->common.aml_opcode, op)); status = AE_AML_BAD_OPCODE; break; diff -Nru a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c --- a/drivers/acpi/dispatcher/dsutils.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/dispatcher/dsutils.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dsutils - Dispatcher utilities - * $Revision: 89 $ + * $Revision: 92 $ * ******************************************************************************/ @@ -74,14 +74,14 @@ * method is parsed separately) However, a method that is * invoked from another method has a parent. */ - if (!op->parent) { + if (!op->common.parent) { return_VALUE (FALSE); } /* * Get info on the parent. The root Op is AML_SCOPE */ - parent_info = acpi_ps_get_opcode_info (op->parent->opcode); + parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode); if (parent_info->class == AML_CLASS_UNKNOWN) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown parent opcode. Op=%p\n", op)); return_VALUE (FALSE); @@ -96,7 +96,7 @@ switch (parent_info->class) { case AML_CLASS_CONTROL: - switch (op->parent->opcode) { + switch (op->common.parent->common.aml_opcode) { case AML_RETURN_OP: /* Never delete the return value associated with a return opcode */ @@ -114,6 +114,11 @@ (walk_state->control_state->control.predicate_op == op)) { goto result_used; } + break; + + default: + /* Ignore other control opcodes */ + break; } /* The general control opcode returns no result */ @@ -132,12 +137,12 @@ case AML_CLASS_NAMED_OBJECT: - if ((op->parent->opcode == AML_REGION_OP) || - (op->parent->opcode == AML_DATA_REGION_OP) || - (op->parent->opcode == AML_PACKAGE_OP) || - (op->parent->opcode == AML_VAR_PACKAGE_OP) || - (op->parent->opcode == AML_BUFFER_OP) || - (op->parent->opcode == AML_INT_EVAL_SUBTREE_OP)) { + if ((op->common.parent->common.aml_opcode == AML_REGION_OP) || + (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) || + (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == AML_BUFFER_OP) || + (op->common.parent->common.aml_opcode == AML_INT_EVAL_SUBTREE_OP)) { /* * These opcodes allow Term_arg(s) as operands and therefore * the operands can be method calls. The result is used. @@ -160,16 +165,16 @@ result_used: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] used by Parent [%s] Op=%p\n", - acpi_ps_get_opcode_name (op->opcode), - acpi_ps_get_opcode_name (op->parent->opcode), op)); + acpi_ps_get_opcode_name (op->common.aml_opcode), + acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op)); return_VALUE (TRUE); result_not_used: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] not used by Parent [%s] Op=%p\n", - acpi_ps_get_opcode_name (op->opcode), - acpi_ps_get_opcode_name (op->parent->opcode), op)); + acpi_ps_get_opcode_name (op->common.aml_opcode), + acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op)); return_VALUE (FALSE); @@ -253,6 +258,7 @@ u32 arg_index) { acpi_status status = AE_OK; + acpi_status status2; NATIVE_CHAR *name_string; u32 name_length; acpi_operand_object *obj_desc; @@ -268,13 +274,13 @@ /* A valid name must be looked up in the namespace */ - if ((arg->opcode == AML_INT_NAMEPATH_OP) && - (arg->value.string)) { + if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && + (arg->common.value.string)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", arg)); /* Get the entire name string from the AML stream */ - status = acpi_ex_get_name_string (ACPI_TYPE_ANY, arg->value.buffer, + status = acpi_ex_get_name_string (ACPI_TYPE_ANY, arg->common.value.buffer, &name_string, &name_length); if (ACPI_FAILURE (status)) { @@ -292,12 +298,12 @@ * IMODE_EXECUTE) in order to support the creation of * namespace objects during the execution of control methods. */ - parent_op = arg->parent; - op_info = acpi_ps_get_opcode_info (parent_op->opcode); + parent_op = arg->common.parent; + op_info = acpi_ps_get_opcode_info (parent_op->common.aml_opcode); if ((op_info->flags & AML_NSNODE) && - (parent_op->opcode != AML_INT_METHODCALL_OP) && - (parent_op->opcode != AML_REGION_OP) && - (parent_op->opcode != AML_INT_NAMEPATH_OP)) { + (parent_op->common.aml_opcode != AML_INT_METHODCALL_OP) && + (parent_op->common.aml_opcode != AML_REGION_OP) && + (parent_op->common.aml_opcode != AML_INT_NAMEPATH_OP)) { /* Enter name into namespace if not found */ interpreter_mode = ACPI_IMODE_LOAD_PASS2; @@ -313,20 +319,20 @@ ACPI_TYPE_ANY, interpreter_mode, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, walk_state, - (acpi_namespace_node **) &obj_desc); + ACPI_CAST_INDIRECT_PTR (acpi_namespace_node, &obj_desc)); /* * The only case where we pass through (ignore) a NOT_FOUND * error is for the Cond_ref_of opcode. */ if (status == AE_NOT_FOUND) { - if (parent_op->opcode == AML_COND_REF_OF_OP) { + if (parent_op->common.aml_opcode == AML_COND_REF_OF_OP) { /* * For the Conditional Reference op, it's OK if * the name is not found; We just need a way to * indicate this to the interpreter, set the * object to the root */ - obj_desc = (acpi_operand_object *) acpi_gbl_root_node; + obj_desc = ACPI_CAST_PTR (acpi_operand_object, acpi_gbl_root_node); status = AE_OK; } @@ -338,10 +344,12 @@ status = AE_AML_NAME_NOT_FOUND; name = NULL; - acpi_ns_externalize_name (ACPI_UINT32_MAX, name_string, NULL, &name); - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Object name [%s] was not found in namespace\n", name)); - ACPI_MEM_FREE (name); + status2 = acpi_ns_externalize_name (ACPI_UINT32_MAX, name_string, NULL, &name); + if (ACPI_SUCCESS (status2)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Object name [%s] was not found in namespace\n", name)); + ACPI_MEM_FREE (name); + } } } @@ -368,7 +376,7 @@ else { /* Check for null name case */ - if (arg->opcode == AML_INT_NAMEPATH_OP) { + if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) { /* * If the name is null, this means that this is an * optional result parameter that was not specified @@ -381,7 +389,7 @@ } else { - opcode = arg->opcode; + opcode = arg->common.aml_opcode; } /* Get the object type of the argument */ @@ -413,7 +421,6 @@ return_ACPI_STATUS (status); } } - else { /* Create an ACPI_INTERNAL_OBJECT for the argument */ @@ -430,7 +437,7 @@ acpi_ut_delete_object_desc (obj_desc); return_ACPI_STATUS (status); } - } + } /* Put the operand object on the object stack */ @@ -487,7 +494,7 @@ /* Move on to next argument, if any */ - arg = arg->next; + arg = arg->common.next; arg_count++; } @@ -500,7 +507,7 @@ * pop everything off of the operand stack and delete those * objects */ - acpi_ds_obj_stack_pop_and_delete (arg_count, walk_state); + (void) acpi_ds_obj_stack_pop_and_delete (arg_count, walk_state); ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While creating Arg %d - %s\n", (arg_count + 1), acpi_format_exception (status))); diff -Nru a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c --- a/drivers/acpi/dispatcher/dswexec.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/dispatcher/dswexec.c Sun Jun 2 18:44:57 2002 @@ -2,7 +2,7 @@ * * Module Name: dswexec - Dispatcher method execution callbacks; * dispatch to interpreter. - * $Revision: 90 $ + * $Revision: 92 $ * *****************************************************************************/ @@ -40,7 +40,7 @@ /* * Dispatch table for opcode classes */ -ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch [] = { +static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch [] = { acpi_ex_opcode_1A_0T_0R, acpi_ex_opcode_1A_0T_1R, acpi_ex_opcode_1A_1T_0R, @@ -200,13 +200,17 @@ op = *out_op; walk_state->op = op; - walk_state->op_info = acpi_ps_get_opcode_info (op->opcode); - walk_state->opcode = op->opcode; + walk_state->opcode = op->common.aml_opcode; + walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); if (acpi_ns_opens_scope (walk_state->op_info->object_type)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n", acpi_ut_get_type_name (walk_state->op_info->object_type), op)); - acpi_ds_scope_stack_pop (walk_state); + + status = acpi_ds_scope_stack_pop (walk_state); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } } @@ -241,7 +245,7 @@ /* We want to send namepaths to the load code */ - if (op->opcode == AML_INT_NAMEPATH_OP) { + if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { opcode_class = AML_CLASS_NAMED_OBJECT; } @@ -273,7 +277,7 @@ status = acpi_ds_load2_begin_op (walk_state, NULL); } - if (op->opcode == AML_REGION_OP) { + if (op->common.aml_opcode == AML_REGION_OP) { status = acpi_ds_result_stack_push (walk_state); } break; @@ -336,11 +340,11 @@ op_class = walk_state->op_info->class; if (op_class == AML_CLASS_UNKNOWN) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown opcode %X\n", op->opcode)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown opcode %X\n", op->common.aml_opcode)); return_ACPI_STATUS (AE_NOT_IMPLEMENTED); } - first_arg = op->value.arg; + first_arg = op->common.value.arg; /* Init the walk state */ @@ -432,8 +436,11 @@ /* 1 Operand, 0 External_result, 0 Internal_result */ status = acpi_ds_exec_end_control_op (walk_state, op); + if (ACPI_FAILURE (status)) { + break; + } - acpi_ds_result_stack_pop (walk_state); + status = acpi_ds_result_stack_pop (walk_state); break; @@ -451,7 +458,7 @@ /* Next_op points to first argument op */ - next_op = next_op->next; + next_op = next_op->common.next; /* * Get the method's arguments and put them on the operand stack @@ -503,26 +510,28 @@ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Executing Create_object (Buffer/Package) Op=%p\n", op)); - switch (op->parent->opcode) { + switch (op->common.parent->common.aml_opcode) { case AML_NAME_OP: /* * Put the Node on the object stack (Contains the ACPI Name of * this object) */ - walk_state->operands[0] = (void *) op->parent->node; + walk_state->operands[0] = (void *) op->common.parent->common.node; walk_state->num_operands = 1; - status = acpi_ds_create_node (walk_state, op->parent->node, op->parent); + status = acpi_ds_create_node (walk_state, op->common.parent->common.node, op->common.parent); if (ACPI_FAILURE (status)) { break; } /* Fall through */ + /*lint -fallthrough */ case AML_INT_EVAL_SUBTREE_OP: - status = acpi_ds_eval_data_object_operands (walk_state, op, acpi_ns_get_attached_object (op->parent->node)); + status = acpi_ds_eval_data_object_operands (walk_state, op, + acpi_ns_get_attached_object (op->common.parent->common.node)); break; default: @@ -552,7 +561,7 @@ break; } - if (op->opcode == AML_REGION_OP) { + if (op->common.aml_opcode == AML_REGION_OP) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Executing Op_region Address/Length Op=%p\n", op)); @@ -585,7 +594,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p\n", - op_class, op_type, op->opcode, op)); + op_class, op_type, op->common.aml_opcode, op)); status = AE_NOT_IMPLEMENTED; break; diff -Nru a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c --- a/drivers/acpi/dispatcher/dswload.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/dispatcher/dswload.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dswload - Dispatcher namespace load callbacks - * $Revision: 62 $ + * $Revision: 66 $ * *****************************************************************************/ @@ -115,21 +115,21 @@ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); - if (op && (op->opcode == AML_INT_NAMEDFIELD_OP)) { + if (op && (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); } /* We are only interested in opcodes that have an associated name */ - if (walk_state->op) { - if (!(walk_state->op_info->flags & AML_NAMED)) { + if (op) { + if (!(walk_state->op_info->flags & AML_NAMED)) { *out_op = op; return (AE_OK); } /* Check if this object has already been installed in the namespace */ - if (op->node) { + if (op->common.node) { *out_op = op; return (AE_OK); } @@ -142,7 +142,7 @@ object_type = walk_state->op_info->object_type; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "State=%p Op=%p Type=%x\n", walk_state, op, object_type)); + "State=%p Op=%p Type=%X\n", walk_state, op, object_type)); /* * Enter the named type into the internal namespace. We enter the name @@ -167,13 +167,13 @@ /* Initialize */ - ((acpi_parse2_object *)op)->name = node->name.integer; + op->named.name = node->name.integer; /* * Put the Node in the "op" object that the parser uses, so we * can get it again quickly when this scope is closed */ - op->node = node; + op->common.node = node; acpi_ps_append_arg (acpi_ps_get_parent_scope (&walk_state->parser_state), op); *out_op = op; @@ -202,6 +202,7 @@ { acpi_parse_object *op; acpi_object_type object_type; + acpi_status status = AE_OK; ACPI_FUNCTION_NAME ("Ds_load1_end_op"); @@ -224,24 +225,26 @@ if (walk_state->opcode == AML_FIELD_OP || walk_state->opcode == AML_BANK_FIELD_OP || walk_state->opcode == AML_INDEX_FIELD_OP) { - acpi_ds_init_field_objects (op, walk_state); + status = acpi_ds_init_field_objects (op, walk_state); } - return (AE_OK); + return (status); } - if (op->opcode == AML_REGION_OP) { - /*Status = */acpi_ex_create_region (((acpi_parse2_object *) op)->data, - ((acpi_parse2_object *) op)->length, - (ACPI_ADR_SPACE_TYPE) ((op->value.arg)->value.integer), walk_state); + if (op->common.aml_opcode == AML_REGION_OP) { + status = acpi_ex_create_region (op->named.data, op->named.length, + (ACPI_ADR_SPACE_TYPE) ((op->common.value.arg)->common.value.integer), walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } } - if (op->opcode == AML_NAME_OP) { + if (op->common.aml_opcode == AML_NAME_OP) { /* For Name opcode, get the object type from the argument */ - if (op->value.arg) { - object_type = (acpi_ps_get_opcode_info ((op->value.arg)->opcode))->object_type; - op->node->type = (u8) object_type; + if (op->common.value.arg) { + object_type = (acpi_ps_get_opcode_info ((op->common.value.arg)->common.aml_opcode))->object_type; + op->common.node->type = (u8) object_type; } } @@ -251,10 +254,10 @@ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n", acpi_ut_get_type_name (object_type), op)); - acpi_ds_scope_stack_pop (walk_state); + status = acpi_ds_scope_stack_pop (walk_state); } - return (AE_OK); + return (status); } @@ -282,7 +285,6 @@ acpi_status status; acpi_object_type object_type; NATIVE_CHAR *buffer_ptr; - void *original = NULL; ACPI_FUNCTION_NAME ("Ds_load2_begin_op"); @@ -305,7 +307,7 @@ if (walk_state->opcode == AML_INT_NAMEPATH_OP) { /* For Namepath op, get the path string */ - buffer_ptr = op->value.string; + buffer_ptr = op->common.value.string; if (!buffer_ptr) { /* No name, just exit */ @@ -315,7 +317,7 @@ else { /* Get name from the op */ - buffer_ptr = (NATIVE_CHAR *) &((acpi_parse2_object *)op)->name; + buffer_ptr = (NATIVE_CHAR *) &op->named.name; } } else { @@ -329,7 +331,7 @@ object_type = walk_state->op_info->object_type; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "State=%p Op=%p Type=%x\n", walk_state, op, object_type)); + "State=%p Op=%p Type=%X\n", walk_state, op, object_type)); if (walk_state->opcode == AML_FIELD_OP || @@ -347,9 +349,12 @@ ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node)); } else { - if (op && op->node) { - original = op->node; - node = op->node; + /* All other opcodes */ + + if (op && op->common.node) { + /* This op/node was previously entered into the namespace */ + + node = op->common.node; if (acpi_ns_opens_scope (object_type)) { status = acpi_ds_scope_stack_push (node, object_type, walk_state); @@ -381,24 +386,19 @@ /* Initialize the new op */ - ((acpi_parse2_object *)op)->name = node->name.integer; - *out_op = op; + if (node) { + op->named.name = node->name.integer; + } + if (out_op) { + *out_op = op; + } } /* * Put the Node in the "op" object that the parser uses, so we * can get it again quickly when this scope is closed */ - op->node = node; - - if (original) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "old %p new %p\n", original, node)); - - if (original != node) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Lookup match error: old %p new %p\n", original, node)); - } - } + op->common.node = node; } return (status); @@ -445,11 +445,11 @@ return (AE_OK); } - if (op->opcode == AML_SCOPE_OP) { + if (op->common.aml_opcode == AML_SCOPE_OP) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Ending scope Op=%p State=%p\n", op, walk_state)); - if (((acpi_parse2_object *)op)->name == ACPI_UINT16_MAX) { + if (op->named.name == ACPI_UINT16_MAX) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unnamed scope! Op=%p State=%p\n", op, walk_state)); return (AE_OK); @@ -463,7 +463,7 @@ * Get the Node/name from the earlier lookup * (It was saved in the *op structure) */ - node = op->node; + node = op->common.node; /* * Put the Node on the object stack (Contains the ACPI Name of @@ -477,7 +477,11 @@ if (acpi_ns_opens_scope (object_type)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n", acpi_ut_get_type_name (object_type), op)); - acpi_ds_scope_stack_pop (walk_state); + + status = acpi_ds_scope_stack_pop (walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } } /* @@ -510,11 +514,11 @@ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Create-Load [%s] State=%p Op=%p Named_obj=%p\n", - acpi_ps_get_opcode_name (op->opcode), walk_state, op, node)); + acpi_ps_get_opcode_name (op->common.aml_opcode), walk_state, op, node)); /* Decode the opcode */ - arg = op->value.arg; + arg = op->common.value.arg; switch (walk_state->op_info->type) { case AML_TYPE_CREATE_FIELD: @@ -529,21 +533,25 @@ case AML_TYPE_NAMED_FIELD: - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_INDEX_FIELD_OP: - status = acpi_ds_create_index_field (op, (acpi_handle) arg->node, + status = acpi_ds_create_index_field (op, (acpi_handle) arg->common.node, walk_state); break; case AML_BANK_FIELD_OP: - status = acpi_ds_create_bank_field (op, arg->node, walk_state); + status = acpi_ds_create_bank_field (op, arg->common.node, walk_state); break; case AML_FIELD_OP: - status = acpi_ds_create_field (op, arg->node, walk_state); + status = acpi_ds_create_field (op, arg->common.node, walk_state); + break; + + default: + /* All NAMED_FIELD opcodes must be handled above */ break; } break; @@ -556,7 +564,7 @@ goto cleanup; } - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_PROCESSOR_OP: status = acpi_ex_create_processor (walk_state); @@ -606,7 +614,7 @@ case AML_TYPE_NAMED_COMPLEX: - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_METHOD_OP: /* * Method_op Pkg_length Name_string Method_flags Term_list @@ -621,9 +629,8 @@ goto cleanup; } - status = acpi_ex_create_method (((acpi_parse2_object *) op)->data, - ((acpi_parse2_object *) op)->length, - walk_state); + status = acpi_ex_create_method (op->named.data, + op->named.length, walk_state); } break; @@ -655,6 +662,11 @@ status = acpi_ds_create_node (walk_state, node, op); break; + + + default: + /* All NAMED_COMPLEX opcodes must be handled above */ + break; } break; @@ -674,7 +686,7 @@ /* * Lookup the method name and save the Node */ - status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string, ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS2, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, walk_state, &(new_node)); @@ -691,7 +703,7 @@ * for now, we will put it in the "op" object that the parser uses, so we * can get it again at the end of this scope */ - op->node = new_node; + op->common.node = new_node; } break; diff -Nru a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c --- a/drivers/acpi/dispatcher/dswstate.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/dispatcher/dswstate.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dswstate - Dispatcher parse tree walk management routines - * $Revision: 59 $ + * $Revision: 64 $ * *****************************************************************************/ @@ -25,11 +25,9 @@ #include "acpi.h" -#include "amlcode.h" #include "acparser.h" #include "acdispat.h" #include "acnamesp.h" -#include "acinterp.h" #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME ("dswstate") @@ -126,13 +124,12 @@ return (AE_NOT_EXIST); } - if (index >= OBJ_NUM_OPERANDS) { + if (index >= OBJ_MAX_OPERAND) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index out of range: %X State=%p Num=%X\n", index, walk_state, state->results.num_results)); } - /* Check for a valid result object */ if (!state->results.obj_desc [index]) { @@ -237,7 +234,7 @@ acpi_operand_object **object, acpi_walk_state *walk_state) { - u32 index; + NATIVE_UINT index; acpi_generic_state *state; @@ -251,7 +248,6 @@ return (AE_NOT_EXIST); } - if (!state->results.num_results) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result objects! State=%p\n", walk_state)); return (AE_AML_NO_RETURN_VALUE); @@ -273,7 +269,7 @@ if (!*object) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null operand! State=%p #Ops=%X, Index=%X\n", - walk_state, state->results.num_results, index)); + walk_state, state->results.num_results, (u32) index)); return (AE_AML_NO_RETURN_VALUE); } @@ -329,7 +325,6 @@ return (AE_BAD_PARAMETER); } - state->results.obj_desc [state->results.num_results] = object; state->results.num_results++; @@ -694,7 +689,6 @@ return_PTR (NULL); } - return_PTR (walk_state->operands[(NATIVE_UINT)(walk_state->num_operands - 1) - index]); } @@ -728,7 +722,6 @@ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Ds_get_current_walk_state, =%p\n", thread->walk_state_list)); - return (thread->walk_state_list); } @@ -918,7 +911,6 @@ walk_state->method_node = method_node; walk_state->method_desc = acpi_ns_get_attached_object (method_node); - /* Push start scope on scope stack and make it current */ status = acpi_ds_scope_stack_push (method_node, ACPI_TYPE_METHOD, walk_state); @@ -928,13 +920,15 @@ /* Init the method arguments */ - acpi_ds_method_data_init_args (params, MTH_NUM_ARGS, walk_state); + status = acpi_ds_method_data_init_args (params, MTH_NUM_ARGS, walk_state); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } - else { /* Setup the current scope */ - parser_state->start_node = parser_state->start_op->node; + parser_state->start_node = parser_state->start_op->common.node; if (parser_state->start_node) { /* Push start scope on scope stack and make it current */ @@ -946,9 +940,8 @@ } } - acpi_ds_init_callbacks (walk_state, pass_number); - - return_ACPI_STATUS (AE_OK); + status = acpi_ds_init_callbacks (walk_state, pass_number); + return_ACPI_STATUS (status); } #endif @@ -983,7 +976,6 @@ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p is not a valid walk state\n", walk_state)); return; } - if (walk_state->parser_state.scope) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p walk still has a scope list\n", walk_state)); diff -Nru a/drivers/acpi/ec.c b/drivers/acpi/ec.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/ec.c Sun Jun 2 18:44:57 2002 @@ -0,0 +1,735 @@ +/* + * acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 31 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_EC_COMPONENT +ACPI_MODULE_NAME ("acpi_ec") + +#define PREFIX "ACPI: " + + +#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ +#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ +#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ + +#define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */ +#define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */ + +#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ +#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ +#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ + +#define ACPI_EC_COMMAND_READ 0x80 +#define ACPI_EC_COMMAND_WRITE 0x81 +#define ACPI_EC_COMMAND_QUERY 0x84 + +static int acpi_ec_add (struct acpi_device *device); +static int acpi_ec_remove (struct acpi_device *device, int type); +static int acpi_ec_start (struct acpi_device *device); +static int acpi_ec_stop (struct acpi_device *device, int type); + +static struct acpi_driver acpi_ec_driver = { + name: ACPI_EC_DRIVER_NAME, + class: ACPI_EC_CLASS, + ids: ACPI_EC_HID, + ops: { + add: acpi_ec_add, + remove: acpi_ec_remove, + start: acpi_ec_start, + stop: acpi_ec_stop, + }, +}; + +struct acpi_ec { + acpi_handle handle; + unsigned long gpe_bit; + unsigned long status_port; + unsigned long command_port; + unsigned long data_port; + unsigned long global_lock; + spinlock_t lock; +}; + + +/* -------------------------------------------------------------------------- + Transaction Management + -------------------------------------------------------------------------- */ + +static int +acpi_ec_wait ( + struct acpi_ec *ec, + u8 event) +{ + u8 acpi_ec_status = 0; + u32 i = ACPI_EC_UDELAY_COUNT; + + if (!ec) + return -EINVAL; + + /* Poll the EC status register waiting for the event to occur. */ + switch (event) { + case ACPI_EC_EVENT_OBF: + do { + acpi_ec_status = inb(ec->status_port); + if (acpi_ec_status & ACPI_EC_FLAG_OBF) + return 0; + udelay(ACPI_EC_UDELAY); + } while (--i>0); + break; + case ACPI_EC_EVENT_IBE: + do { + acpi_ec_status = inb(ec->status_port); + if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) + return 0; + udelay(ACPI_EC_UDELAY); + } while (--i>0); + break; + default: + return -EINVAL; + } + + return -ETIME; +} + + +static int +acpi_ec_read ( + struct acpi_ec *ec, + u8 address, + u8 *data) +{ + acpi_status status = AE_OK; + int result = 0; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_read"); + + if (!ec || !data) + return_VALUE(-EINVAL); + + *data = 0; + + if (ec->global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + spin_lock_irqsave(&ec->lock, flags); + + outb(ACPI_EC_COMMAND_READ, ec->command_port); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + outb(address, ec->data_port); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (result) + goto end; + + *data = inb(ec->data_port); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", + *data, address)); + +end: + spin_unlock_irqrestore(&ec->lock, flags); + + if (ec->global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} + + +static int +acpi_ec_write ( + struct acpi_ec *ec, + u8 address, + u8 data) +{ + int result = 0; + acpi_status status = AE_OK; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_write"); + + if (!ec) + return_VALUE(-EINVAL); + + if (ec->global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + spin_lock_irqsave(&ec->lock, flags); + + outb(ACPI_EC_COMMAND_WRITE, ec->command_port); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + outb(address, ec->data_port); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + outb(data, ec->data_port); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", + data, address)); + +end: + spin_unlock_irqrestore(&ec->lock, flags); + + if (ec->global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} + + +static int +acpi_ec_query ( + struct acpi_ec *ec, + u8 *data) +{ + int result = 0; + acpi_status status = AE_OK; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_query"); + + if (!ec || !data) + return_VALUE(-EINVAL); + + *data = 0; + + if (ec->global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + /* + * Query the EC to find out which _Qxx method we need to evaluate. + * Note that successful completion of the query causes the ACPI_EC_SCI + * bit to be cleared (and thus clearing the interrupt source). + */ + + spin_lock_irqsave(&ec->lock, flags); + + outb(ACPI_EC_COMMAND_QUERY, ec->command_port); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (result) + goto end; + + *data = inb(ec->data_port); + if (!*data) + result = -ENODATA; + +end: + spin_unlock_irqrestore(&ec->lock, flags); + + if (ec->global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} + + +/* -------------------------------------------------------------------------- + Event Management + -------------------------------------------------------------------------- */ + +struct acpi_ec_query_data { + acpi_handle handle; + u8 data; +}; + + +static void +acpi_ec_gpe_query ( + void *data) +{ + struct acpi_ec_query_data *query_data = NULL; + static char object_name[5] = {'_','Q','0','0','\0'}; + const char hex[] = {'0','1','2','3','4','5','6','7', + '8','9','A','B','C','D','E','F'}; + + ACPI_FUNCTION_TRACE("acpi_ec_gpe_query"); + + if (!data) + return; + + query_data = (struct acpi_ec_query_data *) data; + + object_name[2] = hex[((query_data->data >> 4) & 0x0F)]; + object_name[3] = hex[(query_data->data & 0x0F)]; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); + + acpi_evaluate(query_data->handle, object_name, NULL, NULL); + + kfree(query_data); + + return; +} + + +static void +acpi_ec_gpe_handler ( + void *data) +{ + acpi_status status = AE_OK; + struct acpi_ec *ec = (struct acpi_ec *) data; + u8 value = 0; + unsigned long flags = 0; + struct acpi_ec_query_data *query_data = NULL; + + if (!ec) + return; + + spin_lock_irqsave(&ec->lock, flags); + value = inb(ec->command_port); + spin_unlock_irqrestore(&ec->lock, flags); + + /* TBD: Implement asynch events! + * NOTE: All we care about are EC-SCI's. Other EC events are + * handled via polling (yuck!). This is because some systems + * treat EC-SCIs as level (versus EDGE!) triggered, preventing + * a purely interrupt-driven approach (grumble, grumble). + */ + + if (!(value & ACPI_EC_FLAG_SCI)) + return; + + if (acpi_ec_query(ec, &value)) + return; + + query_data = kmalloc(sizeof(struct acpi_ec_query_data), GFP_ATOMIC); + if (!query_data) + return; + query_data->handle = ec->handle; + query_data->data = value; + + status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, + acpi_ec_gpe_query, query_data); + if (ACPI_FAILURE(status)) + kfree(query_data); + + return; +} + + +/* -------------------------------------------------------------------------- + Address Space Management + -------------------------------------------------------------------------- */ + +static acpi_status +acpi_ec_space_setup ( + acpi_handle region_handle, + u32 function, + void *handler_context, + void **return_context) +{ + /* + * The EC object is in the handler context and is needed + * when calling the acpi_ec_space_handler. + */ + *return_context = handler_context; + + return AE_OK; +} + + +static acpi_status +acpi_ec_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + acpi_integer *value, + void *handler_context, + void *region_context) +{ + int result = 0; + struct acpi_ec *ec = NULL; + + ACPI_FUNCTION_TRACE("acpi_ec_space_handler"); + + if ((address > 0xFF) || (bit_width != 8) || !value || !handler_context) + return_VALUE(AE_BAD_PARAMETER); + + ec = (struct acpi_ec *) handler_context; + + switch (function) { + case ACPI_READ: + result = acpi_ec_read(ec, (u8) address, (u8*) value); + break; + case ACPI_WRITE: + result = acpi_ec_write(ec, (u8) address, (u8) *value); + break; + default: + result = -EINVAL; + break; + } + + switch (result) { + case -EINVAL: + return_VALUE(AE_BAD_PARAMETER); + break; + case -ENODEV: + return_VALUE(AE_NOT_FOUND); + break; + case -ETIME: + return_VALUE(AE_TIME); + break; + default: + return_VALUE(AE_OK); + } + +} + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +struct proc_dir_entry *acpi_ec_dir = NULL; + + +static int +acpi_ec_read_info ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_ec *ec = (struct acpi_ec *) data; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_read_info"); + + if (!ec || (off != 0)) + goto end; + + p += sprintf(p, "gpe bit: 0x%02x\n", + (u32) ec->gpe_bit); + p += sprintf(p, "ports: 0x%02x, 0x%02x\n", + (u32) ec->status_port, (u32) ec->data_port); + p += sprintf(p, "use global lock: %s\n", + ec->global_lock?"yes":"no"); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_ec_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_ec_add_fs"); + + if (!acpi_ec_dir) { + acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir); + if (!acpi_ec_dir) + return_VALUE(-ENODEV); + } + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_ec_dir); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + } + + entry = create_proc_read_entry(ACPI_EC_FILE_INFO, S_IRUGO, + acpi_device_dir(device), acpi_ec_read_info, + acpi_driver_data(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_WARN, + "Unable to create '%s' fs entry\n", + ACPI_EC_FILE_INFO)); + + return_VALUE(0); +} + + +static int +acpi_ec_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_ec_remove_fs"); + + if (!acpi_ec_dir) + return_VALUE(-ENODEV); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_ec_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +static int +acpi_ec_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_ec *ec = NULL; + + ACPI_FUNCTION_TRACE("acpi_ec_add"); + + if (!device) + return_VALUE(-EINVAL); + + ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + if (!ec) + return_VALUE(-ENOMEM); + memset(ec, 0, sizeof(struct acpi_ec)); + + ec->handle = device->handle; + ec->lock = SPIN_LOCK_UNLOCKED; + sprintf(acpi_device_name(device), "%s", ACPI_EC_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_EC_CLASS); + acpi_driver_data(device) = ec; + + /* Use the global lock for all EC transactions? */ + acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock); + + /* Get GPE bit assignment (EC events). */ + status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe_bit); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error obtaining GPE bit assignment\n")); + result = -ENODEV; + goto end; + } + + result = acpi_ec_add_fs(device); + if (result) + goto end; + + printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", + acpi_device_name(device), acpi_device_bid(device), + (u32) ec->gpe_bit); + +end: + if (result) + kfree(ec); + + return_VALUE(result); +} + + +static int +acpi_ec_remove ( + struct acpi_device *device, + int type) +{ + struct acpi_ec *ec = NULL; + + ACPI_FUNCTION_TRACE("acpi_ec_remove"); + + if (!device) + return_VALUE(-EINVAL); + + ec = (struct acpi_ec *) acpi_driver_data(device); + + acpi_ec_remove_fs(device); + + kfree(ec); + + return_VALUE(0); +} + + +static int +acpi_ec_start ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_ec *ec = NULL; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_resource *resource = NULL; + + ACPI_FUNCTION_TRACE("acpi_ec_start"); + + if (!device) + return_VALUE(-EINVAL); + + ec = (struct acpi_ec *) acpi_driver_data(device); + + if (!ec) + return_VALUE(-EINVAL); + + /* + * Get I/O port addresses + */ + + status = acpi_get_current_resources(ec->handle, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses")); + return_VALUE(-ENODEV); + } + + resource = (acpi_resource *) buffer.pointer; + if (!resource || (resource->id != ACPI_RSTYPE_IO)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid or missing resource\n")); + result = -ENODEV; + goto end; + } + ec->data_port = resource->data.io.min_base_address; + + resource = ACPI_NEXT_RESOURCE(resource); + if (!resource || (resource->id != ACPI_RSTYPE_IO)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid or missing resource\n")); + result = -ENODEV; + goto end; + } + ec->command_port = ec->status_port = resource->data.io.min_base_address; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n", + (u32) ec->gpe_bit, (u32) ec->command_port, (u32) ec->data_port)); + + /* + * Install GPE handler + */ + + status = acpi_install_gpe_handler(ec->gpe_bit, + ACPI_EVENT_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + status = acpi_install_address_space_handler (ec->handle, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, + &acpi_ec_space_setup, ec); + if (ACPI_FAILURE(status)) { + acpi_remove_address_space_handler(ec->handle, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); + return_VALUE(-ENODEV); + } +end: + kfree(buffer.pointer); + + return_VALUE(result); +} + + +static int +acpi_ec_stop ( + struct acpi_device *device, + int type) +{ + acpi_status status = AE_OK; + struct acpi_ec *ec = NULL; + + ACPI_FUNCTION_TRACE("acpi_ec_stop"); + + if (!device) + return_VALUE(-EINVAL); + + ec = (struct acpi_ec *) acpi_driver_data(device); + + status = acpi_remove_address_space_handler(ec->handle, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + status = acpi_remove_gpe_handler(ec->gpe_bit, &acpi_ec_gpe_handler); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + + +int __init +acpi_ec_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_init"); + + result = acpi_bus_register_driver(&acpi_ec_driver); + if (result < 0) { + remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +void __exit +acpi_ec_exit (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_exit"); + + result = acpi_bus_unregister_driver(&acpi_ec_driver); + if (!result) + remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir); + + return_VOID; +} diff -Nru a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c --- a/drivers/acpi/events/evevent.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/events/evevent.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evevent - Fixed and General Purpose Even handling and dispatch - * $Revision: 78 $ + * $Revision: 88 $ * *****************************************************************************/ @@ -24,7 +24,6 @@ */ #include "acpi.h" -#include "achware.h" #include "acevents.h" #include "acnamesp.h" @@ -159,6 +158,7 @@ void) { NATIVE_UINT i; + acpi_status status; /* @@ -172,8 +172,11 @@ /* Enable the fixed event */ if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) { - acpi_hw_bit_register_write (acpi_gbl_fixed_event_info[i].enable_register_id, + status = acpi_set_register (acpi_gbl_fixed_event_info[i].enable_register_id, 0, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return (status); + } } } @@ -200,7 +203,7 @@ u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; u32 gpe_status; u32 gpe_enable; - NATIVE_UINT i; + NATIVE_UINT_MAX32 i; ACPI_FUNCTION_NAME ("Ev_fixed_event_detect"); @@ -208,10 +211,10 @@ /* * Read the fixed feature status and enable registers, as all the cases - * depend on their values. + * depend on their values. Ignore errors here. */ - gpe_status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS); - gpe_enable = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE); + (void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, &gpe_status); + (void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE, &gpe_enable); ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, "Fixed Acpi_event Block: Enable %08X Status %08X\n", @@ -259,7 +262,7 @@ /* Clear the status bit */ - acpi_hw_bit_register_write (acpi_gbl_fixed_event_info[event].status_register_id, + (void) acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id, 1, ACPI_MTX_DO_NOT_LOCK); /* @@ -267,7 +270,7 @@ * The event is disabled to prevent further interrupts. */ if (NULL == acpi_gbl_fixed_event_handlers[event].handler) { - acpi_hw_bit_register_write (acpi_gbl_fixed_event_info[event].enable_register_id, + (void) acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id, 0, ACPI_MTX_DO_NOT_LOCK); ACPI_REPORT_ERROR ( @@ -299,13 +302,14 @@ acpi_status acpi_ev_gpe_initialize (void) { - NATIVE_UINT i; - NATIVE_UINT j; - NATIVE_UINT gpe_block; + NATIVE_UINT_MAX32 i; + NATIVE_UINT_MAX32 j; + u32 gpe_block; u32 gpe_register; u32 gpe_number_index; u32 gpe_number; ACPI_GPE_REGISTER_INFO *gpe_register_info; + acpi_status status; ACPI_FUNCTION_TRACE ("Ev_gpe_initialize"); @@ -372,8 +376,9 @@ /* * Allocate the GPE number-to-index translation table */ - acpi_gbl_gpe_number_to_index = ACPI_MEM_CALLOCATE (sizeof (ACPI_GPE_INDEX_INFO) * - (acpi_gbl_gpe_number_max + 1)); + acpi_gbl_gpe_number_to_index = ACPI_MEM_CALLOCATE ( + sizeof (ACPI_GPE_INDEX_INFO) * + ((ACPI_SIZE) acpi_gbl_gpe_number_max + 1)); if (!acpi_gbl_gpe_number_to_index) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the Gpe_number_to_index table\n")); @@ -383,12 +388,13 @@ /* Set the Gpe index table to GPE_INVALID */ ACPI_MEMSET (acpi_gbl_gpe_number_to_index, (int) ACPI_GPE_INVALID, - sizeof (ACPI_GPE_INDEX_INFO) * (acpi_gbl_gpe_number_max + 1)); + sizeof (ACPI_GPE_INDEX_INFO) * ((ACPI_SIZE) acpi_gbl_gpe_number_max + 1)); /* * Allocate the GPE register information block */ - acpi_gbl_gpe_register_info = ACPI_MEM_CALLOCATE (acpi_gbl_gpe_register_count * + acpi_gbl_gpe_register_info = ACPI_MEM_CALLOCATE ( + (ACPI_SIZE) acpi_gbl_gpe_register_count * sizeof (ACPI_GPE_REGISTER_INFO)); if (!acpi_gbl_gpe_register_info) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, @@ -400,7 +406,8 @@ * Allocate the GPE dispatch handler block. There are eight distinct GPEs * per register. Initialization to zeros is sufficient. */ - acpi_gbl_gpe_number_info = ACPI_MEM_CALLOCATE (ACPI_MUL_8 (acpi_gbl_gpe_register_count) * + acpi_gbl_gpe_number_info = ACPI_MEM_CALLOCATE ( + (ACPI_SIZE) ACPI_MUL_8 (acpi_gbl_gpe_register_count) * sizeof (ACPI_GPE_NUMBER_INFO)); if (!acpi_gbl_gpe_number_info) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the Gpe_number_info table\n")); @@ -423,14 +430,17 @@ /* Init the Register info for this entire GPE register (8 GPEs) */ - gpe_register_info->base_gpe_number = (u8) (acpi_gbl_gpe_block_info[gpe_block].block_base_number + (ACPI_MUL_8 (i))); + gpe_register_info->base_gpe_number = (u8) (acpi_gbl_gpe_block_info[gpe_block].block_base_number + + (ACPI_MUL_8 (i))); ACPI_STORE_ADDRESS (gpe_register_info->status_address.address, - (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address) + i)); + (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address) + + i)); ACPI_STORE_ADDRESS (gpe_register_info->enable_address.address, - (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address) + i + - acpi_gbl_gpe_block_info[gpe_block].register_count)); + (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address) + + i + + acpi_gbl_gpe_block_info[gpe_block].register_count)); gpe_register_info->status_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].address_space_id; gpe_register_info->enable_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].address_space_id; @@ -455,19 +465,26 @@ * by writing a '0'. */ - acpi_hw_low_level_write (8, 0x00, &gpe_register_info->enable_address, 0); - acpi_hw_low_level_write (8, 0xFF, &gpe_register_info->status_address, 0); + status = acpi_hw_low_level_write (8, 0x00, &gpe_register_info->enable_address, 0); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_hw_low_level_write (8, 0xFF, &gpe_register_info->status_address, 0); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } gpe_register++; } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE Block%d: %X registers at %8.8X%8.8X\n", - gpe_block, acpi_gbl_gpe_block_info[0].register_count, - ACPI_HIDWORD (acpi_gbl_gpe_block_info[gpe_block].block_address->address), - ACPI_LODWORD (acpi_gbl_gpe_block_info[gpe_block].block_address->address))); + (s32) gpe_block, acpi_gbl_gpe_block_info[0].register_count, + ACPI_HIDWORD (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address)), + ACPI_LODWORD (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address)))); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE Block%d Range GPE #%2.2X to GPE #%2.2X\n", - gpe_block, + (s32) gpe_block, acpi_gbl_gpe_block_info[gpe_block].block_base_number, acpi_gbl_gpe_block_info[gpe_block].block_base_number + ((acpi_gbl_gpe_block_info[gpe_block].register_count * 8) -1))); @@ -520,6 +537,7 @@ u32 gpe_number_index; NATIVE_CHAR name[ACPI_NAME_SIZE + 1]; u8 type; + acpi_status status; ACPI_FUNCTION_NAME ("Ev_save_method_info"); @@ -528,7 +546,7 @@ /* Extract the name from the object and convert to a string */ ACPI_MOVE_UNALIGNED32_TO_32 (name, - &((acpi_namespace_node *) obj_handle)->name); + &((acpi_namespace_node *) obj_handle)->name.integer); name[ACPI_NAME_SIZE] = 0; /* @@ -583,7 +601,10 @@ /* * Enable the GPE (SCIs should be disabled at this point) */ - acpi_hw_enable_gpe (gpe_number); + status = acpi_hw_enable_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + return (status); + } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Registered GPE method %s as GPE number %X\n", name, gpe_number)); @@ -652,6 +673,8 @@ u8 enabled_status_byte; u8 bit_mask; ACPI_GPE_REGISTER_INFO *gpe_register_info; + u32 in_value; + acpi_status status; ACPI_FUNCTION_NAME ("Ev_gpe_detect"); @@ -665,16 +688,22 @@ for (i = 0; i < acpi_gbl_gpe_register_count; i++) { gpe_register_info = &acpi_gbl_gpe_register_info[i]; - gpe_register_info->status = (u8) acpi_hw_low_level_read (8, - &gpe_register_info->status_address, 0); + status = acpi_hw_low_level_read (8, &in_value, &gpe_register_info->status_address, 0); + gpe_register_info->status = (u8) in_value; + if (ACPI_FAILURE (status)) { + return (ACPI_INTERRUPT_NOT_HANDLED); + } - gpe_register_info->enable = (u8) acpi_hw_low_level_read (8, - &gpe_register_info->enable_address, 0); + status = acpi_hw_low_level_read (8, &in_value, &gpe_register_info->enable_address, 0); + gpe_register_info->enable = (u8) in_value; + if (ACPI_FAILURE (status)) { + return (ACPI_INTERRUPT_NOT_HANDLED); + } ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, - "GPE block at %8.8X%8.8X - Enable %08X Status %08X\n", - ACPI_HIDWORD (gpe_register_info->enable_address.address), - ACPI_LODWORD (gpe_register_info->enable_address.address), + "GPE block at %8.8X%8.8X - Values: Enable %02X Status %02X\n", + ACPI_HIDWORD (ACPI_GET_ADDRESS (gpe_register_info->enable_address.address)), + ACPI_LODWORD (ACPI_GET_ADDRESS (gpe_register_info->enable_address.address)), gpe_register_info->enable, gpe_register_info->status)); @@ -731,6 +760,7 @@ u32 gpe_number = (u32) ACPI_TO_INTEGER (context); u32 gpe_number_index; ACPI_GPE_NUMBER_INFO gpe_info; + acpi_status status; ACPI_FUNCTION_TRACE ("Ev_asynch_execute_gpe_method"); @@ -745,12 +775,14 @@ * Take a snapshot of the GPE info for this level - we copy the * info to prevent a race condition with Remove_handler. */ - if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_EVENTS))) { + status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (status)) { return_VOID; } gpe_info = acpi_gbl_gpe_number_info [gpe_number_index]; - if (ACPI_FAILURE (acpi_ut_release_mutex (ACPI_MTX_EVENTS))) { + status = acpi_ut_release_mutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (status)) { return_VOID; } @@ -759,7 +791,11 @@ * Invoke the GPE Method (_Lxx, _Exx): * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.) */ - acpi_ns_evaluate_by_handle (gpe_info.method_handle, NULL, NULL); + status = acpi_ns_evaluate_by_handle (gpe_info.method_handle, NULL, NULL); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("%s while evaluated GPE%X method\n", + acpi_format_exception (status), gpe_number)); + } } if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) { @@ -767,13 +803,16 @@ * GPE is level-triggered, we clear the GPE status bit after handling * the event. */ - acpi_hw_clear_gpe (gpe_number); + status = acpi_hw_clear_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + return_VOID; + } } /* * Enable the GPE. */ - acpi_hw_enable_gpe (gpe_number); + (void) acpi_hw_enable_gpe (gpe_number); return_VOID; } @@ -798,6 +837,7 @@ { u32 gpe_number_index; ACPI_GPE_NUMBER_INFO *gpe_info; + acpi_status status; ACPI_FUNCTION_TRACE ("Ev_gpe_dispatch"); @@ -820,7 +860,11 @@ * level-triggered events are cleared after the GPE is serviced. */ if (gpe_info->type & ACPI_EVENT_EDGE_TRIGGERED) { - acpi_hw_clear_gpe (gpe_number); + status = acpi_hw_clear_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to clear GPE[%X]\n", gpe_number)); + return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); + } } /* @@ -840,7 +884,11 @@ * Disable GPE, so it doesn't keep firing before the method has a * chance to run. */ - acpi_hw_disable_gpe (gpe_number); + status = acpi_hw_disable_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to disable GPE[%X]\n", gpe_number)); + return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); + } /* * Execute the method associated with the GPE. @@ -860,14 +908,22 @@ * Disable the GPE. The GPE will remain disabled until the ACPI * Core Subsystem is restarted, or the handler is reinstalled. */ - acpi_hw_disable_gpe (gpe_number); + status = acpi_hw_disable_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to disable GPE[%X]\n", gpe_number)); + return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); + } } /* * It is now safe to clear level-triggered evnets. */ if (gpe_info->type & ACPI_EVENT_LEVEL_TRIGGERED) { - acpi_hw_clear_gpe (gpe_number); + status = acpi_hw_clear_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to clear GPE[%X]\n", gpe_number)); + return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); + } } return_VALUE (ACPI_INTERRUPT_HANDLED); diff -Nru a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c --- a/drivers/acpi/events/evmisc.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/events/evmisc.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evmisc - Miscellaneous event manager support functions - * $Revision: 48 $ + * $Revision: 53 $ * *****************************************************************************/ @@ -27,7 +27,6 @@ #include "acevents.h" #include "acnamesp.h" #include "acinterp.h" -#include "achware.h" #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evmisc") @@ -178,7 +177,7 @@ } /* - * Get the notify object attached to the device Node + * Get the notify object attached to the NS Node */ obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { @@ -186,25 +185,21 @@ switch (node->type) { case ACPI_TYPE_DEVICE: - - if (notify_value <= ACPI_MAX_SYS_NOTIFY) { - handler_obj = obj_desc->device.sys_handler; - } - else { - handler_obj = obj_desc->device.drv_handler; - } - break; - - case ACPI_TYPE_THERMAL: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_POWER: if (notify_value <= ACPI_MAX_SYS_NOTIFY) { - handler_obj = obj_desc->thermal_zone.sys_handler; + handler_obj = obj_desc->common_notify.sys_handler; } else { - handler_obj = obj_desc->thermal_zone.drv_handler; + handler_obj = obj_desc->common_notify.drv_handler; } break; + + default: + /* All other types are not supported */ + return (AE_TYPE); } } @@ -323,14 +318,19 @@ acpi_ev_global_lock_thread ( void *context) { + acpi_status status; + /* Signal threads that are waiting for the lock */ if (acpi_gbl_global_lock_thread_count) { /* Send sufficient units to the semaphore */ - acpi_os_signal_semaphore (acpi_gbl_global_lock_semaphore, + status = acpi_os_signal_semaphore (acpi_gbl_global_lock_semaphore, acpi_gbl_global_lock_thread_count); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not signal Global Lock semaphore\n")); + } } } @@ -352,6 +352,7 @@ void *context) { u8 acquired = FALSE; + acpi_status status; /* @@ -367,8 +368,14 @@ /* Run the Global Lock thread which will signal all waiting threads */ - acpi_os_queue_for_execution (OSD_PRIORITY_HIGH, acpi_ev_global_lock_thread, - context); + status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH, + acpi_ev_global_lock_thread, context); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not queue Global Lock thread, %s\n", + acpi_format_exception (status))); + + return (ACPI_INTERRUPT_NOT_HANDLED); + } } return (ACPI_INTERRUPT_HANDLED); @@ -487,10 +494,11 @@ * ******************************************************************************/ -void +acpi_status acpi_ev_release_global_lock (void) { u8 pending = FALSE; + acpi_status status = AE_OK; ACPI_FUNCTION_TRACE ("Ev_release_global_lock"); @@ -498,7 +506,7 @@ if (!acpi_gbl_global_lock_thread_count) { ACPI_REPORT_WARNING(("Cannot release HW Global Lock, it has not been acquired\n")); - return_VOID; + return_ACPI_STATUS (AE_NOT_ACQUIRED); } /* One fewer thread has the global lock */ @@ -507,7 +515,7 @@ if (acpi_gbl_global_lock_thread_count) { /* There are still some threads holding the lock, cannot release */ - return_VOID; + return_ACPI_STATUS (AE_OK); } /* @@ -522,10 +530,10 @@ * register */ if (pending) { - acpi_hw_bit_register_write (ACPI_BITREG_GLOBAL_LOCK_RELEASE, 1, ACPI_MTX_LOCK); + status = acpi_set_register (ACPI_BITREG_GLOBAL_LOCK_RELEASE, 1, ACPI_MTX_LOCK); } - return_VOID; + return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c --- a/drivers/acpi/events/evregion.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/events/evregion.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evregion - ACPI Address_space (Op_region) handler dispatch - * $Revision: 128 $ + * $Revision: 133 $ * *****************************************************************************/ @@ -28,7 +28,6 @@ #include "acevents.h" #include "acnamesp.h" #include "acinterp.h" -#include "amlcode.h" #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evregion") @@ -36,7 +35,7 @@ /******************************************************************************* * - * FUNCTION: Acpi_ev_install_default_address_space_handlers + * FUNCTION: Acpi_ev_init_address_spaces * * PARAMETERS: * @@ -47,13 +46,13 @@ ******************************************************************************/ acpi_status -acpi_ev_install_default_address_space_handlers ( +acpi_ev_init_address_spaces ( void) { acpi_status status; - ACPI_FUNCTION_TRACE ("Ev_install_default_address_space_handlers"); + ACPI_FUNCTION_TRACE ("Ev_init_address_spaces"); /* @@ -166,7 +165,7 @@ /* * Set up the parameter objects */ - params[0]->integer.value = region_obj->region.space_id; + params[0]->integer.value = region_obj->region.space_id; params[1]->integer.value = function; params[2] = NULL; @@ -209,9 +208,10 @@ u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, - acpi_integer *value) + void *value) { acpi_status status; + acpi_status status2; acpi_adr_space_handler handler; acpi_adr_space_setup region_setup; acpi_operand_object *handler_desc; @@ -267,7 +267,10 @@ /* Re-enter the interpreter */ - acpi_ex_enter_interpreter (); + status2 = acpi_ex_enter_interpreter (); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } /* * Init routine may fail @@ -325,7 +328,10 @@ * We just returned from a non-default handler, we must re-enter the * interpreter */ - acpi_ex_enter_interpreter (); + status2 = acpi_ex_enter_interpreter (); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } } return_ACPI_STATUS (status); @@ -333,7 +339,7 @@ /******************************************************************************* * - * FUNCTION: Acpi_ev_disassociate_region_from_handler + * FUNCTION: Acpi_ev_detach_region * * PARAMETERS: Region_obj - Region Object * Acpi_ns_is_locked - Namespace Region Already Locked? @@ -346,7 +352,7 @@ ******************************************************************************/ void -acpi_ev_disassociate_region_from_handler( +acpi_ev_detach_region( acpi_operand_object *region_obj, u8 acpi_ns_is_locked) { @@ -359,12 +365,12 @@ acpi_status status; - ACPI_FUNCTION_TRACE ("Ev_disassociate_region_from_handler"); + ACPI_FUNCTION_TRACE ("Ev_detach_region"); region_obj2 = acpi_ns_get_secondary_object (region_obj); if (!region_obj2) { - return; + return_VOID; } region_context = region_obj2->extra.region_context; @@ -410,7 +416,12 @@ /* * Now stop region accesses by executing the _REG method */ - acpi_ev_execute_reg_method (region_obj, 0); + status = acpi_ev_execute_reg_method (region_obj, 0); + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n", + acpi_format_exception (status), + acpi_ut_get_region_name (region_obj->region.space_id))); + } if (acpi_ns_is_locked) { status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); @@ -473,7 +484,7 @@ /******************************************************************************* * - * FUNCTION: Acpi_ev_associate_region_and_handler + * FUNCTION: Acpi_ev_attach_region * * PARAMETERS: Handler_obj - Handler Object * Region_obj - Region Object @@ -487,15 +498,16 @@ ******************************************************************************/ acpi_status -acpi_ev_associate_region_and_handler ( +acpi_ev_attach_region ( acpi_operand_object *handler_obj, acpi_operand_object *region_obj, u8 acpi_ns_is_locked) { - acpi_status status; + acpi_status status; + acpi_status status2; - ACPI_FUNCTION_TRACE ("Ev_associate_region_and_handler"); + ACPI_FUNCTION_TRACE ("Ev_attach_region"); ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, @@ -519,13 +531,19 @@ * method */ if (acpi_ns_is_locked) { - acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + status2 = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } } status = acpi_ev_execute_reg_method (region_obj, 1); if (acpi_ns_is_locked) { - (void) acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + status2 = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status2)) { + return_ACPI_STATUS (status2); + } } return_ACPI_STATUS (status); @@ -665,12 +683,12 @@ * * First disconnect region for any previous handler (if any) */ - acpi_ev_disassociate_region_from_handler (obj_desc, FALSE); + acpi_ev_detach_region (obj_desc, FALSE); /* * Then connect the region to the new handler */ - status = acpi_ev_associate_region_and_handler (handler_obj, obj_desc, FALSE); + status = acpi_ev_attach_region (handler_obj, obj_desc, FALSE); return (status); } diff -Nru a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c --- a/drivers/acpi/events/evrgnini.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/events/evrgnini.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evrgnini- ACPI Address_space (Op_region) init - * $Revision: 57 $ + * $Revision: 61 $ * *****************************************************************************/ @@ -27,8 +27,6 @@ #include "acpi.h" #include "acevents.h" #include "acnamesp.h" -#include "acinterp.h" -#include "amlcode.h" #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evrgnini") @@ -205,12 +203,12 @@ status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node, &temp); /* - * The default is zero, since the allocation above zeroed the data, just - * do nothing on failures. + * The default is zero, and since the allocation above zeroed + * the data, just do nothing on failure. */ if (ACPI_SUCCESS (status)) { - pci_id->device = ACPI_HIWORD (temp); - pci_id->function = ACPI_LOWORD (temp); + pci_id->device = ACPI_HIWORD (ACPI_LODWORD (temp)); + pci_id->function = ACPI_LOWORD (ACPI_LODWORD (temp)); } /* @@ -235,9 +233,13 @@ if (ACPI_SUCCESS (status)) { if (!(ACPI_STRNCMP (object_hID.buffer, PCI_ROOT_HID_STRING, sizeof (PCI_ROOT_HID_STRING)))) { - acpi_install_address_space_handler ((acpi_handle) node, + status = acpi_install_address_space_handler ((acpi_handle) node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not install handler for %4.4s, %s\n", + node->name.ascii, acpi_format_exception (status))); + } break; } } @@ -457,7 +459,7 @@ obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { /* - * can only be a handler if the object exists + * Can only be a handler if the object exists */ switch (node->type) { case ACPI_TYPE_DEVICE: @@ -474,6 +476,10 @@ handler_obj = obj_desc->thermal_zone.addr_handler; break; + + default: + /* Ignore other objects */ + break; } while (handler_obj) { @@ -489,8 +495,8 @@ /* * Found it! Now update the region and the handler */ - acpi_ev_associate_region_and_handler (handler_obj, region_obj, - acpi_ns_locked); + status = acpi_ev_attach_region (handler_obj, region_obj, + acpi_ns_locked); return_ACPI_STATUS (AE_OK); } diff -Nru a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c --- a/drivers/acpi/events/evsci.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/events/evsci.c Sun Jun 2 18:44:58 2002 @@ -2,7 +2,7 @@ * * Module Name: evsci - System Control Interrupt configuration and * legacy to ACPI mode state transition functions - * $Revision: 83 $ + * $Revision: 86 $ * ******************************************************************************/ @@ -25,8 +25,6 @@ */ #include "acpi.h" -#include "acnamesp.h" -#include "achware.h" #include "acevents.h" @@ -53,6 +51,8 @@ void *context) { u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED; + u32 value; + acpi_status status; ACPI_FUNCTION_TRACE("Ev_sci_handler"); @@ -62,7 +62,12 @@ * Make sure that ACPI is enabled by checking SCI_EN. Note that we are * required to treat the SCI interrupt as sharable, level, active low. */ - if (!acpi_hw_bit_register_read (ACPI_BITREG_SCI_ENABLE, ACPI_MTX_DO_NOT_LOCK)) { + status = acpi_get_register (ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE (status)) { + return (ACPI_INTERRUPT_NOT_HANDLED); + } + + if (!value) { /* ACPI is not enabled; this interrupt cannot be for us */ return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); @@ -135,15 +140,18 @@ acpi_status acpi_ev_remove_sci_handler (void) { + acpi_status status; + + ACPI_FUNCTION_TRACE ("Ev_remove_sci_handler"); /* Just let the OS remove the handler and disable the level */ - acpi_os_remove_interrupt_handler ((u32) acpi_gbl_FADT->sci_int, + status = acpi_os_remove_interrupt_handler ((u32) acpi_gbl_FADT->sci_int, acpi_ev_sci_handler); - return_ACPI_STATUS (AE_OK); + return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c --- a/drivers/acpi/events/evxface.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/events/evxface.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evxface - External interfaces for ACPI events - * $Revision: 126 $ + * $Revision: 128 $ * *****************************************************************************/ @@ -25,10 +25,8 @@ #include "acpi.h" -#include "achware.h" #include "acnamesp.h" #include "acevents.h" -#include "amlcode.h" #include "acinterp.h" #define _COMPONENT ACPI_EVENTS @@ -516,8 +514,12 @@ /* Clear the GPE (of stale events), the enable it */ - acpi_hw_clear_gpe (gpe_number); - acpi_hw_enable_gpe (gpe_number); + status = acpi_hw_clear_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_hw_enable_gpe (gpe_number); cleanup: @@ -566,7 +568,10 @@ /* Disable the GPE before removing the handler */ - acpi_hw_disable_gpe (gpe_number); + status = acpi_hw_disable_gpe (gpe_number); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (status)) { @@ -576,7 +581,7 @@ /* Make sure that the installed handler is the same */ if (acpi_gbl_gpe_number_info[gpe_number_index].handler != handler) { - acpi_hw_enable_gpe (gpe_number); + (void) acpi_hw_enable_gpe (gpe_number); status = AE_BAD_PARAMETER; goto cleanup; } @@ -651,13 +656,15 @@ acpi_release_global_lock ( u32 handle) { + acpi_status status; + if (handle != acpi_gbl_global_lock_handle) { return (AE_NOT_ACQUIRED); } - acpi_ev_release_global_lock (); - return (AE_OK); + status = acpi_ev_release_global_lock (); + return (status); } diff -Nru a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c --- a/drivers/acpi/events/evxfevnt.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/events/evxfevnt.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable - * $Revision: 51 $ + * $Revision: 55 $ * *****************************************************************************/ @@ -25,11 +25,7 @@ #include "acpi.h" -#include "achware.h" -#include "acnamesp.h" #include "acevents.h" -#include "amlcode.h" -#include "acinterp.h" #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evxfevnt") @@ -118,7 +114,7 @@ /* Unload the SCI interrupt handler */ - acpi_ev_remove_sci_handler (); + status = acpi_ev_remove_sci_handler (); return_ACPI_STATUS (status); } @@ -144,6 +140,7 @@ u32 flags) { acpi_status status = AE_OK; + u32 value; ACPI_FUNCTION_TRACE ("Acpi_enable_event"); @@ -156,7 +153,7 @@ /* Decode the Fixed Event */ - if (event > ACPI_NUM_FIXED_EVENTS) { + if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS (AE_BAD_PARAMETER); } @@ -164,13 +161,21 @@ * Enable the requested fixed event (by writing a one to the * enable register bit) */ - acpi_hw_bit_register_write (acpi_gbl_fixed_event_info[event].enable_register_id, - 1, ACPI_MTX_LOCK); + status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id, + 1, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* Make sure that the hardware responded */ - if (1 != acpi_hw_bit_register_read (acpi_gbl_fixed_event_info[event].enable_register_id, - ACPI_MTX_LOCK)) { + status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id, + &value, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + if (value != 1) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not enable %s event\n", acpi_ut_get_event_name (event))); return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); @@ -188,7 +193,10 @@ /* Enable the requested GPE number */ - acpi_hw_enable_gpe (event); + status = acpi_hw_enable_gpe (event); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } if (flags & ACPI_EVENT_WAKE_ENABLE) { acpi_hw_enable_gpe_for_wakeup (event); @@ -226,6 +234,7 @@ u32 flags) { acpi_status status = AE_OK; + u32 value; ACPI_FUNCTION_TRACE ("Acpi_disable_event"); @@ -238,7 +247,7 @@ /* Decode the Fixed Event */ - if (event > ACPI_NUM_FIXED_EVENTS) { + if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS (AE_BAD_PARAMETER); } @@ -246,11 +255,19 @@ * Disable the requested fixed event (by writing a zero to the * enable register bit) */ - acpi_hw_bit_register_write (acpi_gbl_fixed_event_info[event].enable_register_id, - 0, ACPI_MTX_LOCK); + status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id, + 0, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id, + &value, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - if (0 != acpi_hw_bit_register_read (acpi_gbl_fixed_event_info[event].enable_register_id, - ACPI_MTX_LOCK)) { + if (value != 0) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not disable %s events\n", acpi_ut_get_event_name (event))); return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); @@ -275,7 +292,7 @@ acpi_hw_disable_gpe_for_wakeup (event); } else { - acpi_hw_disable_gpe (event); + status = acpi_hw_disable_gpe (event); } break; @@ -319,7 +336,7 @@ /* Decode the Fixed Event */ - if (event > ACPI_NUM_FIXED_EVENTS) { + if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS (AE_BAD_PARAMETER); } @@ -327,7 +344,7 @@ * Clear the requested fixed event (By writing a one to the * status register bit) */ - acpi_hw_bit_register_write (acpi_gbl_fixed_event_info[event].status_register_id, + status = acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id, 1, ACPI_MTX_LOCK); break; @@ -340,7 +357,7 @@ return_ACPI_STATUS (AE_BAD_PARAMETER); } - acpi_hw_clear_gpe (event); + status = acpi_hw_clear_gpe (event); break; @@ -393,14 +410,14 @@ /* Decode the Fixed Event */ - if (event > ACPI_NUM_FIXED_EVENTS) { + if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Get the status of the requested fixed event */ - *event_status = acpi_hw_bit_register_read (acpi_gbl_fixed_event_info[event].status_register_id, - ACPI_MTX_LOCK); + status = acpi_get_register (acpi_gbl_fixed_event_info[event].status_register_id, + event_status, ACPI_MTX_LOCK); break; @@ -414,7 +431,7 @@ /* Obtain status on the requested GPE number */ - acpi_hw_get_gpe_status (event, event_status); + status = acpi_hw_get_gpe_status (event, event_status); break; diff -Nru a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c --- a/drivers/acpi/events/evxfregn.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/events/evxfregn.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ * * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and * Address Spaces. - * $Revision: 48 $ + * $Revision: 50 $ * *****************************************************************************/ @@ -26,10 +26,8 @@ #include "acpi.h" -#include "achware.h" #include "acnamesp.h" #include "acevents.h" -#include "amlcode.h" #include "acinterp.h" #define _COMPONENT ACPI_EVENTS @@ -356,7 +354,7 @@ * The region is just inaccessible as indicated to * the _REG method */ - acpi_ev_disassociate_region_from_handler(region_obj, TRUE); + acpi_ev_detach_region (region_obj, TRUE); /* * Walk the list, since we took the first region and it diff -Nru a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c --- a/drivers/acpi/executer/exconfig.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/executer/exconfig.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes) - * $Revision: 60 $ + * $Revision: 65 $ * *****************************************************************************/ @@ -25,13 +25,11 @@ #include "acpi.h" -#include "acparser.h" #include "acinterp.h" #include "amlcode.h" #include "acnamesp.h" #include "acevents.h" #include "actables.h" -#include "acdispat.h" #define _COMPONENT ACPI_EXECUTER @@ -77,11 +75,11 @@ /* Install the new table into the local data structures */ table_info.pointer = table; - table_info.length = table->length; + table_info.length = (ACPI_SIZE) table->length; table_info.allocation = ACPI_MEM_ALLOCATED; table_info.base_pointer = table; - status = acpi_tb_install_table (NULL, &table_info); + status = acpi_tb_install_table (&table_info); if (ACPI_FAILURE (status)) { goto cleanup; } @@ -92,7 +90,7 @@ if (ACPI_FAILURE (status)) { /* Uninstall table on error */ - acpi_tb_uninstall_table (table_info.installed_desc); + (void) acpi_tb_uninstall_table (table_info.installed_desc); goto cleanup; } @@ -227,10 +225,10 @@ if (parameter_node) { /* Store the parameter data into the optional parameter object */ - status = acpi_ex_store (operand[5], (acpi_operand_object *) parameter_node, + status = acpi_ex_store (operand[5], ACPI_CAST_PTR (acpi_operand_object, parameter_node), walk_state); if (ACPI_FAILURE (status)) { - acpi_ex_unload_table (ddb_handle); + (void) acpi_ex_unload_table (ddb_handle); } } @@ -267,7 +265,6 @@ acpi_table_header table_header; u32 i; - ACPI_FUNCTION_TRACE ("Ex_load_op"); @@ -285,7 +282,7 @@ for (i = 0; i < sizeof (acpi_table_header); i++) { status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ, (ACPI_PHYSICAL_ADDRESS) i, 8, - (acpi_integer *) ((u8 *) &table_header + i)); + ((u8 *) &table_header) + i); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -308,7 +305,7 @@ for (i = 0; i < table_header.length; i++) { status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ, (ACPI_PHYSICAL_ADDRESS) i, 8, - (acpi_integer *) (table_data_ptr + i)); + ((u8 *) table_data_ptr + i)); if (ACPI_FAILURE (status)) { goto cleanup; } @@ -334,7 +331,7 @@ goto cleanup; } - table_ptr = (acpi_table_header *) buffer_desc->buffer.pointer; + table_ptr = ACPI_CAST_PTR (acpi_table_header, buffer_desc->buffer.pointer); break; @@ -352,7 +349,7 @@ acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].sig_length))) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Table has invalid signature [%4.4s], must be SSDT or PSDT\n", - (char *) &table_ptr->signature)); + table_ptr->signature)); status = AE_BAD_SIGNATURE; goto cleanup; } @@ -368,7 +365,7 @@ status = acpi_ex_store (ddb_handle, target, walk_state); if (ACPI_FAILURE (status)) { - acpi_ex_unload_table (ddb_handle); + (void) acpi_ex_unload_table (ddb_handle); } return_ACPI_STATUS (status); @@ -417,7 +414,7 @@ * validated here. */ if ((!ddb_handle) || - (ACPI_GET_DESCRIPTOR_TYPE (ddb_handle) != ACPI_DESC_TYPE_INTERNAL) || + (ACPI_GET_DESCRIPTOR_TYPE (ddb_handle) != ACPI_DESC_TYPE_OPERAND) || (((acpi_operand_object *)ddb_handle)->common.type != INTERNAL_TYPE_REFERENCE)) { return_ACPI_STATUS (AE_BAD_PARAMETER); @@ -431,14 +428,11 @@ * Delete the entire namespace under this table Node * (Offset contains the Table_id) */ - status = acpi_ns_delete_namespace_by_owner (table_info->table_id); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + acpi_ns_delete_namespace_by_owner (table_info->table_id); /* Delete the table itself */ - acpi_tb_uninstall_table (table_info->installed_desc); + (void) acpi_tb_uninstall_table (table_info->installed_desc); /* Delete the table descriptor (Ddb_handle) */ diff -Nru a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c --- a/drivers/acpi/executer/exconvrt.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/executer/exconvrt.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exconvrt - Object conversion routines - * $Revision: 32 $ + * $Revision: 35 $ * *****************************************************************************/ @@ -25,12 +25,8 @@ #include "acpi.h" -#include "acparser.h" -#include "acnamesp.h" #include "acinterp.h" -#include "acevents.h" #include "amlcode.h" -#include "acdispat.h" #define _COMPONENT ACPI_EXECUTER @@ -60,9 +56,9 @@ u32 i; acpi_operand_object *ret_desc; u32 count; - char *pointer; + u8 *pointer; acpi_integer result; - u32 integer_size = sizeof (acpi_integer); + acpi_status status; ACPI_FUNCTION_TRACE_PTR ("Ex_convert_to_integer", obj_desc); @@ -74,12 +70,12 @@ return_ACPI_STATUS (AE_OK); case ACPI_TYPE_STRING: - pointer = obj_desc->string.pointer; + pointer = (u8 *) obj_desc->string.pointer; count = obj_desc->string.length; break; case ACPI_TYPE_BUFFER: - pointer = (char *) obj_desc->buffer.pointer; + pointer = obj_desc->buffer.pointer; count = obj_desc->buffer.length; break; @@ -88,24 +84,6 @@ } /* - * Create a new integer - */ - ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc) { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ - - if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { - /* - * We are running a method that exists in a 32-bit ACPI table. - * Truncate the value to 32 bits by zeroing out the upper 32-bit field - */ - integer_size = sizeof (u32); - } - - /* * Convert the buffer/string to an integer. Note that both buffers and * strings are treated as raw data - we don't convert ascii to hex for * strings. @@ -118,8 +96,8 @@ /* Transfer no more than an integer's worth of data */ - if (count > integer_size) { - count = integer_size; + if (count > acpi_gbl_integer_byte_width) { + count = acpi_gbl_integer_byte_width; } /* @@ -128,13 +106,14 @@ switch (obj_desc->common.type) { case ACPI_TYPE_STRING: - /* TBD: Need to use 64-bit ACPI_STRTOUL */ - /* * Convert string to an integer * String must be hexadecimal as per the ACPI specification */ - result = ACPI_STRTOUL (pointer, NULL, 16); + status = acpi_ut_strtoul64 ((char *) pointer, 16, &result); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } break; @@ -153,6 +132,19 @@ result |= (((acpi_integer) pointer[i]) << (i * 8)); } break; + + + default: + /* No other types can get here */ + break; + } + + /* + * Create a new integer + */ + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); } /* Save the Result, delete original descriptor, store new descriptor */ @@ -192,7 +184,6 @@ { acpi_operand_object *ret_desc; u32 i; - u32 integer_size = sizeof (acpi_integer); u8 *new_buf; @@ -210,20 +201,10 @@ return_ACPI_STATUS (AE_NO_MEMORY); } - /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ - - if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { - /* - * We are running a method that exists in a 32-bit ACPI table. - * Use only 32 bits of the Integer for conversion. - */ - integer_size = sizeof (u32); - } - /* Need enough space for one integer */ - ret_desc->buffer.length = integer_size; - new_buf = ACPI_MEM_CALLOCATE (integer_size); + ret_desc->buffer.length = acpi_gbl_integer_byte_width; + new_buf = ACPI_MEM_CALLOCATE (acpi_gbl_integer_byte_width); if (!new_buf) { ACPI_REPORT_ERROR (("Ex_convert_to_buffer: Buffer allocation failure\n")); @@ -233,7 +214,7 @@ /* Copy the integer to the buffer */ - for (i = 0; i < integer_size; i++) { + for (i = 0; i < acpi_gbl_integer_byte_width; i++) { new_buf[i] = (u8) (obj_desc->integer.value >> (i * 8)); } ret_desc->buffer.pointer = new_buf; @@ -286,7 +267,7 @@ u32 i; u32 j; u32 k = 0; - u8 hex_digit; + char hex_digit; acpi_integer digit; u32 remainder; u32 length = sizeof (acpi_integer); @@ -305,7 +286,7 @@ digit = integer; for (j = 1; j < i; j++) { - acpi_ut_short_divide (&digit, 10, &digit, &remainder); + (void) acpi_ut_short_divide (&digit, 10, &digit, &remainder); } /* Create the decimal digit */ @@ -333,7 +314,7 @@ } if (!leading_zero) { - string[k] = hex_digit; + string[k] = (u8) hex_digit; k++; } } @@ -385,7 +366,6 @@ u32 i; u32 index; u32 string_length; - u32 integer_size = sizeof (acpi_integer); u8 *new_buf; u8 *pointer; @@ -396,17 +376,7 @@ switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: - /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ - - if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { - /* - * We are running a method that exists in a 32-bit ACPI table. - * Use only 32 bits of the Integer - */ - integer_size = sizeof (u32); - } - - string_length = integer_size * 2; + string_length = acpi_gbl_integer_byte_width * 2; if (base == 10) { string_length = ACPI_MAX_DECIMAL_DIGITS; } @@ -421,7 +391,7 @@ /* Need enough space for one ASCII integer plus null terminator */ - new_buf = ACPI_MEM_CALLOCATE (string_length + 1); + new_buf = ACPI_MEM_CALLOCATE ((ACPI_SIZE) string_length + 1); if (!new_buf) { ACPI_REPORT_ERROR (("Ex_convert_to_string: Buffer allocation failure\n")); @@ -429,7 +399,6 @@ return_ACPI_STATUS (AE_NO_MEMORY); } - /* Convert */ i = acpi_ex_convert_to_ascii (obj_desc->integer.value, base, new_buf); @@ -486,7 +455,7 @@ string_length = max_length; } - new_buf = ACPI_MEM_CALLOCATE (string_length + 1); + new_buf = ACPI_MEM_CALLOCATE ((ACPI_SIZE) string_length + 1); if (!new_buf) { ACPI_REPORT_ERROR (("Ex_convert_to_string: Buffer allocation failure\n")); @@ -500,7 +469,7 @@ pointer = obj_desc->buffer.pointer; index = 0; for (i = 0, index = 0; i < obj_desc->buffer.length; i++) { - index = acpi_ex_convert_to_ascii (pointer[i], base, &new_buf[index]); + index = acpi_ex_convert_to_ascii ((acpi_integer) pointer[i], base, &new_buf[index]); new_buf[index] = ' '; index++; @@ -512,7 +481,6 @@ ret_desc->buffer.pointer = new_buf; ret_desc->string.length = ACPI_STRLEN ((char *) new_buf); - /* Return the new buffer descriptor */ if (*result_desc == obj_desc) { @@ -641,6 +609,11 @@ */ status = acpi_ex_convert_to_buffer (source_desc, result_desc, walk_state); break; + + + default: + status = AE_AML_INTERNAL; + break; } break; @@ -660,7 +633,6 @@ status = AE_AML_INTERNAL; } - /* * Source-to-Target conversion semantics: diff -Nru a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c --- a/drivers/acpi/executer/excreate.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/executer/excreate.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: excreate - Named object creation - * $Revision: 89 $ + * $Revision: 91 $ * *****************************************************************************/ @@ -25,12 +25,10 @@ #include "acpi.h" -#include "acparser.h" #include "acinterp.h" #include "amlcode.h" #include "acnamesp.h" #include "acevents.h" -#include "acdispat.h" #include "actables.h" @@ -234,7 +232,7 @@ /* Get the Node from the object stack */ - node = walk_state->op->node; + node = walk_state->op->common.node; /* * If the region object is already attached to this node, @@ -323,7 +321,7 @@ /* Get the Node from the object stack */ - node = walk_state->op->node; + node = walk_state->op->common.node; /* * If the region object is already attached to this node, diff -Nru a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c --- a/drivers/acpi/executer/exdump.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/executer/exdump.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exdump - Interpreter debug output routines - * $Revision: 147 $ + * $Revision: 153 $ * *****************************************************************************/ @@ -28,7 +28,6 @@ #include "acinterp.h" #include "amlcode.h" #include "acnamesp.h" -#include "actables.h" #include "acparser.h" #define _COMPONENT ACPI_EXECUTER @@ -43,90 +42,6 @@ /***************************************************************************** * - * FUNCTION: Acpi_ex_show_hex_value - * - * PARAMETERS: Byte_count - Number of bytes to print (1, 2, or 4) - * *Aml_start - Address in AML stream of bytes to print - * Interpreter_mode - Current running mode (load1/Load2/Exec) - * Lead_space - # of spaces to print ahead of value - * 0 => none ahead but one behind - * - * DESCRIPTION: Print Byte_count byte(s) starting at Aml_start as a single - * value, in hex. If Byte_count > 1 or the value printed is > 9, also - * print in decimal. - * - ****************************************************************************/ - -void -acpi_ex_show_hex_value ( - u32 byte_count, - u8 *aml_start, - u32 lead_space) -{ - u32 value; /* Value retrieved from AML stream */ - u32 show_decimal_value; - u32 length; /* Length of printed field */ - u8 *current_aml_ptr = NULL; /* Pointer to current byte of AML value */ - - - ACPI_FUNCTION_TRACE ("Ex_show_hex_value"); - - - if (!((ACPI_LV_LOAD & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) { - return; - } - - if (!aml_start) { - ACPI_REPORT_ERROR (("Ex_show_hex_value: null pointer\n")); - return; - } - - /* - * AML numbers are always stored little-endian, - * even if the processor is big-endian. - */ - for (current_aml_ptr = aml_start + byte_count, - value = 0; - current_aml_ptr > aml_start; ) { - value = (value << 8) + (u32)* --current_aml_ptr; - } - - length = lead_space * byte_count + 2; - if (byte_count > 1) { - length += (byte_count - 1); - } - - show_decimal_value = (byte_count > 1 || value > 9); - if (show_decimal_value) { - length += 3 + acpi_ex_digits_needed (value, 10); - } - - for (length = lead_space; length; --length ) { - acpi_os_printf (" "); - } - - while (byte_count--) { - acpi_os_printf ("%02x", *aml_start++); - if (byte_count) { - acpi_os_printf (" "); - } - } - - if (show_decimal_value) { - acpi_os_printf (" [%d]", value); - } - - if (0 == lead_space) { - acpi_os_printf (" "); - } - - acpi_os_printf ("\n"); - return_VOID; -} - - -/***************************************************************************** - * * FUNCTION: Acpi_ex_dump_operand * * PARAMETERS: *Obj_desc - Pointer to entry to be dumped @@ -137,20 +52,22 @@ * ****************************************************************************/ -acpi_status +void acpi_ex_dump_operand ( acpi_operand_object *obj_desc) { u8 *buf = NULL; u32 length; u32 i; + acpi_operand_object **element; + u16 element_index; ACPI_FUNCTION_NAME ("Ex_dump_operand") if (!((ACPI_LV_EXEC & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) { - return (AE_OK); + return; } if (!obj_desc) { @@ -160,19 +77,19 @@ * code that dumps the stack expects something to be there! */ acpi_os_printf ("Null stack entry ptr\n"); - return (AE_OK); + return; } if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p NS Node: ", obj_desc)); ACPI_DUMP_ENTRY (obj_desc, ACPI_LV_EXEC); - return (AE_OK); + return; } - if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_INTERNAL) { + if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p is not a local object\n", obj_desc)); ACPI_DUMP_BUFFER (obj_desc, sizeof (acpi_operand_object)); - return (AE_OK); + return; } /* Obj_desc is a valid object */ @@ -265,7 +182,7 @@ case AML_INT_NAMEPATH_OP: acpi_os_printf ("Reference.Node->Name %X\n", - obj_desc->reference.node->name); + obj_desc->reference.node->name.integer); break; default: @@ -343,18 +260,13 @@ if (obj_desc->package.count && obj_desc->package.elements && acpi_dbg_level > 1) { - acpi_operand_object**element; - u16 element_index; - for (element_index = 0, element = obj_desc->package.elements; element_index < obj_desc->package.count; ++element_index, ++element) { acpi_ex_dump_operand (*element); } } - acpi_os_printf ("\n"); - break; @@ -389,7 +301,6 @@ acpi_os_printf ("%c", obj_desc->string.pointer[i]); } - acpi_os_printf ("\"\n"); break; @@ -429,13 +340,11 @@ { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*NULL* \n")); } - else if (ACPI_TYPE_BUFFER != obj_desc->buffer_field.buffer_obj->common.type) { acpi_os_printf ("*not a Buffer* \n"); } - else { ACPI_DUMP_STACK_ENTRY (obj_desc->buffer_field.buffer_obj); @@ -490,13 +399,13 @@ default: - /* unknown Obj_desc->Common.Type value */ + /* Unknown Obj_desc->Common.Type value */ acpi_os_printf ("Unknown Type %X\n", obj_desc->common.type); break; } - return (AE_OK); + return; } @@ -540,7 +449,6 @@ note = "?"; } - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "************* Operand Stack Contents (Opcode [%s], %d Operands)\n", ident, num_levels)); @@ -550,16 +458,12 @@ num_levels = 1; } - /* Dump the stack starting at the top, working down */ + /* Dump the operand stack starting at the top */ for (i = 0; num_levels > 0; i--, num_levels--) { obj_desc = &operands[i]; - - if (ACPI_FAILURE (acpi_ex_dump_operand (*obj_desc))) - { - break; - } + acpi_ex_dump_operand (*obj_desc); } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, @@ -611,7 +515,8 @@ char *title, ACPI_PHYSICAL_ADDRESS value) { -#ifdef _IA16 + +#if ACPI_MACHINE_WIDTH == 16 acpi_os_printf ("%20s : %p\n", title, value); #else acpi_os_printf ("%20s : %8.8X%8.8X\n", title, @@ -648,8 +553,7 @@ } } - - acpi_os_printf ("%20s : %4.4s\n", "Name", (char *) &node->name); + acpi_os_printf ("%20s : %4.4s\n", "Name", node->name.ascii); acpi_ex_out_string ("Type", acpi_ut_get_type_name (node->type)); acpi_ex_out_integer ("Flags", node->flags); acpi_ex_out_integer ("Owner Id", node->owner_id); @@ -691,7 +595,7 @@ } } - if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_INTERNAL) + if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { acpi_os_printf ("Ex_dump_object_descriptor: %p is not a valid ACPI object\n", obj_desc); return; @@ -709,7 +613,7 @@ { case ACPI_TYPE_INTEGER: - acpi_os_printf ("%20s : %X%8.8X\n", "Value", + acpi_os_printf ("%20s : %8.8X%8.8X\n", "Value", ACPI_HIDWORD (obj_desc->integer.value), ACPI_LODWORD (obj_desc->integer.value)); break; @@ -739,7 +643,7 @@ if (obj_desc->package.count > 0) { - acpi_os_printf ("\n_package Contents:\n"); + acpi_os_printf ("\nPackage Contents:\n"); for (i = 0; i < obj_desc->package.count; i++) { acpi_os_printf ("[%.3d] %p", i, obj_desc->package.elements[i]); @@ -811,7 +715,7 @@ acpi_ex_out_integer ("Processor ID", obj_desc->processor.proc_id); acpi_ex_out_integer ("Length", obj_desc->processor.length); - acpi_ex_out_integer ("Address", obj_desc->processor.address); + acpi_ex_out_address ("Address", (ACPI_PHYSICAL_ADDRESS) obj_desc->processor.address); acpi_ex_out_pointer ("Sys_handler", obj_desc->processor.sys_handler); acpi_ex_out_pointer ("Drv_handler", obj_desc->processor.drv_handler); acpi_ex_out_pointer ("Addr_handler", obj_desc->processor.addr_handler); @@ -861,6 +765,10 @@ acpi_ex_out_integer ("Value", obj_desc->index_field.value); acpi_ex_out_pointer ("Index", obj_desc->index_field.index_obj); acpi_ex_out_pointer ("Data", obj_desc->index_field.data_obj); + break; + + default: + /* All object types covered above */ break; } break; diff -Nru a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c --- a/drivers/acpi/executer/exfield.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/executer/exfield.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exfield - ACPI AML (p-code) execution - field manipulation - * $Revision: 108 $ + * $Revision: 110 $ * *****************************************************************************/ @@ -27,10 +27,6 @@ #include "acpi.h" #include "acdispat.h" #include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "achware.h" -#include "acevents.h" #define _COMPONENT ACPI_EXECUTER @@ -61,7 +57,6 @@ acpi_status status; acpi_operand_object *buffer_desc; u32 length; - u32 integer_size; void *buffer; u8 locked; @@ -99,19 +94,7 @@ * Note: Field.length is in bits. */ length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->field.bit_length); - - /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ - - integer_size = sizeof (acpi_integer); - if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { - /* - * We are running a method that exists in a 32-bit ACPI table. - * Integer size is 4. - */ - integer_size = sizeof (u32); - } - - if (length > integer_size) { + if (length > acpi_gbl_integer_byte_width) { /* Field is too large for an Integer, create a Buffer instead */ buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); @@ -139,7 +122,7 @@ return_ACPI_STATUS (AE_NO_MEMORY); } - length = integer_size; + length = acpi_gbl_integer_byte_width; buffer_desc->integer.value = 0; buffer = &buffer_desc->integer.value; } diff -Nru a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c --- a/drivers/acpi/executer/exfldio.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/executer/exfldio.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exfldio - Aml Field I/O - * $Revision: 84 $ + * $Revision: 86 $ * *****************************************************************************/ @@ -27,8 +27,6 @@ #include "acpi.h" #include "acinterp.h" #include "amlcode.h" -#include "acnamesp.h" -#include "achware.h" #include "acevents.h" #include "acdispat.h" @@ -67,7 +65,7 @@ rgn_desc = obj_desc->common_field.region_obj; if (ACPI_TYPE_REGION != rgn_desc->common.type) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %x %s\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n", rgn_desc->common.type, acpi_ut_get_type_name (rgn_desc->common.type))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } @@ -99,8 +97,8 @@ */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n", - (char *) &obj_desc->common_field.node->name, obj_desc->common_field.access_byte_width, - (char *) &rgn_desc->region.node->name, rgn_desc->region.length)); + obj_desc->common_field.node->name.ascii, obj_desc->common_field.access_byte_width, + rgn_desc->region.node->name.ascii, rgn_desc->region.length)); } /* @@ -109,9 +107,9 @@ */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n", - (char *) &obj_desc->common_field.node->name, obj_desc->common_field.base_byte_offset, + obj_desc->common_field.node->name.ascii, obj_desc->common_field.base_byte_offset, field_datum_byte_offset, obj_desc->common_field.access_byte_width, - (char *) &rgn_desc->region.node->name, rgn_desc->region.length)); + rgn_desc->region.node->name.ascii, rgn_desc->region.length)); return_ACPI_STATUS (AE_AML_REGION_LIMIT); } @@ -235,7 +233,7 @@ return (FALSE); } - if (value >= (acpi_integer) (1 << obj_desc->common_field.bit_length)) { + if (value >= ((acpi_integer) 1 << obj_desc->common_field.bit_length)) { /* * The Value is larger than the maximum value that can fit into * the register. @@ -343,7 +341,7 @@ /* Ensure that the Bank_value is not beyond the capacity of the register */ if (acpi_ex_register_overflow (obj_desc->bank_field.bank_obj, - obj_desc->bank_field.value)) { + (acpi_integer) obj_desc->bank_field.value)) { return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); } @@ -363,7 +361,7 @@ * Region_field case and write the datum to the Operation Region */ - /* No break; ! */ + /*lint -fallthrough */ case INTERNAL_TYPE_REGION_FIELD: @@ -387,7 +385,7 @@ /* Ensure that the Index_value is not beyond the capacity of the register */ if (acpi_ex_register_overflow (obj_desc->index_field.index_obj, - obj_desc->index_field.value)) { + (acpi_integer) obj_desc->index_field.value)) { return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); } @@ -472,7 +470,7 @@ /* If the mask is all ones, we don't need to worry about the update rule */ - if (mask != ACPI_UINT32_MAX) { + if (mask != ACPI_INTEGER_MAX) { /* Decode the update rule */ switch (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK) { @@ -509,7 +507,7 @@ default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Write_with_update_rule: Unknown Update_rule setting: %x\n", + "Write_with_update_rule: Unknown Update_rule setting: %X\n", (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK))); return_ACPI_STATUS (AE_AML_OPERAND_VALUE); } @@ -579,6 +577,10 @@ ACPI_MOVE_UNALIGNED64_TO_64 (datum, &(((u64 *) buffer) [offset])); break; + + default: + /* Should not get here */ + break; } } @@ -631,6 +633,10 @@ ACPI_MOVE_UNALIGNED64_TO_64 (&(((u64 *) buffer)[offset]), &merged_datum); break; + + default: + /* Should not get here */ + break; } } @@ -685,7 +691,7 @@ obj_desc->common_field.access_byte_width); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Byte_len=%x, Datum_len=%x, Byte_gran=%x\n", + "Byte_len=%X, Datum_len=%X, Byte_gran=%X\n", byte_field_length, datum_count,obj_desc->common_field.access_byte_width)); /* @@ -863,7 +869,7 @@ datum_count = ACPI_ROUND_UP_TO (byte_field_length, obj_desc->common_field.access_byte_width); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Byte_len=%x, Datum_len=%x, Byte_gran=%x\n", + "Byte_len=%X, Datum_len=%X, Byte_gran=%X\n", byte_field_length, datum_count, obj_desc->common_field.access_byte_width)); /* diff -Nru a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c --- a/drivers/acpi/executer/exmisc.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/executer/exmisc.c Sun Jun 2 18:44:57 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes - * $Revision: 100 $ + * $Revision: 104 $ * *****************************************************************************/ @@ -26,7 +26,6 @@ #include "acpi.h" -#include "acparser.h" #include "acinterp.h" #include "amlcode.h" #include "acdispat.h" @@ -63,7 +62,7 @@ switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) { - case ACPI_DESC_TYPE_INTERNAL: + case ACPI_DESC_TYPE_OPERAND: if (obj_desc->common.type != INTERNAL_TYPE_REFERENCE) { *return_desc = NULL; @@ -81,7 +80,7 @@ status = acpi_ds_method_data_get_node (obj_desc->reference.opcode, obj_desc->reference.offset, walk_state, - (acpi_namespace_node **) return_desc); + ACPI_CAST_INDIRECT_PTR (acpi_namespace_node, return_desc)); break; default: @@ -189,11 +188,11 @@ * Point the return object to the new buffer */ return_desc->buffer.pointer = (u8 *) new_buf; - return_desc->buffer.length = length1 + length2; + return_desc->buffer.length = (u32) (length1 + length2); /* Compute the new checksum */ - new_buf[return_desc->buffer.length - 1] = + new_buf[return_desc->buffer.length - 1] = (NATIVE_CHAR) acpi_ut_generate_checksum (return_desc->buffer.pointer, (return_desc->buffer.length - 1)); @@ -237,7 +236,6 @@ acpi_integer this_integer; acpi_operand_object *return_desc; NATIVE_CHAR *new_buf; - u32 integer_size = sizeof (acpi_integer); ACPI_FUNCTION_ENTRY (); @@ -252,17 +250,6 @@ switch (obj_desc1->common.type) { case ACPI_TYPE_INTEGER: - /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ - - if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { - /* - * We are running a method that exists in a 32-bit ACPI table. - * Truncate the value to 32 bits by zeroing out the upper - * 32-bit field - */ - integer_size = sizeof (u32); - } - /* Result of two integers is a buffer */ return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); @@ -272,7 +259,7 @@ /* Need enough space for two integers */ - return_desc->buffer.length = integer_size * 2; + return_desc->buffer.length = acpi_gbl_integer_byte_width * 2; new_buf = ACPI_MEM_CALLOCATE (return_desc->buffer.length); if (!new_buf) { ACPI_REPORT_ERROR @@ -286,16 +273,16 @@ /* Convert the first integer */ this_integer = obj_desc1->integer.value; - for (i = 0; i < integer_size; i++) { - new_buf[i] = (u8) this_integer; + for (i = 0; i < acpi_gbl_integer_byte_width; i++) { + new_buf[i] = (NATIVE_CHAR) this_integer; this_integer >>= 8; } /* Convert the second integer */ this_integer = obj_desc2->integer.value; - for (; i < (integer_size * 2); i++) { - new_buf[i] = (u8) this_integer; + for (; i < (ACPI_MUL_2 (acpi_gbl_integer_byte_width)); i++) { + new_buf[i] = (NATIVE_CHAR) this_integer; this_integer >>= 8; } @@ -311,8 +298,8 @@ /* Operand0 is string */ - new_buf = ACPI_MEM_ALLOCATE (obj_desc1->string.length + - obj_desc2->string.length + 1); + new_buf = ACPI_MEM_ALLOCATE ((ACPI_SIZE) obj_desc1->string.length + + (ACPI_SIZE) obj_desc2->string.length + 1); if (!new_buf) { ACPI_REPORT_ERROR (("Ex_do_concatenate: String allocation failure\n")); @@ -341,8 +328,8 @@ return (AE_NO_MEMORY); } - new_buf = ACPI_MEM_ALLOCATE (obj_desc1->buffer.length + - obj_desc2->buffer.length); + new_buf = ACPI_MEM_ALLOCATE ((ACPI_SIZE) obj_desc1->buffer.length + + (ACPI_SIZE) obj_desc2->buffer.length); if (!new_buf) { ACPI_REPORT_ERROR (("Ex_do_concatenate: Buffer allocation failure\n")); @@ -530,6 +517,9 @@ if (operand0 || operand1) { return (TRUE); } + break; + + default: break; } diff -Nru a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c --- a/drivers/acpi/executer/exmutex.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/executer/exmutex.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exmutex - ASL Mutex Acquire/Release functions - * $Revision: 10 $ + * $Revision: 13 $ * *****************************************************************************/ @@ -27,9 +27,6 @@ #include "acpi.h" #include "acinterp.h" -#include "acnamesp.h" -#include "achware.h" -#include "acevents.h" #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME ("exmutex") @@ -269,12 +266,13 @@ * ******************************************************************************/ -acpi_status +void acpi_ex_release_all_mutexes ( ACPI_THREAD_STATE *thread) { acpi_operand_object *next = thread->acquired_mutex_list; acpi_operand_object *this; + acpi_status status; ACPI_FUNCTION_ENTRY (); @@ -293,14 +291,15 @@ /* Release the mutex */ - acpi_ex_system_release_mutex (this); + status = acpi_ex_system_release_mutex (this); + if (ACPI_FAILURE (status)) { + continue; + } /* Mark mutex unowned */ this->mutex.owner_thread = NULL; } - - return (AE_OK); } diff -Nru a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c --- a/drivers/acpi/executer/exnames.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/executer/exnames.c Sun Jun 2 18:44:57 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exnames - interpreter/scanner name load/execute - * $Revision: 90 $ + * $Revision: 91 $ * *****************************************************************************/ @@ -28,7 +28,6 @@ #include "acpi.h" #include "acinterp.h" #include "amlcode.h" -#include "acnamesp.h" #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME ("exnames") @@ -148,10 +147,10 @@ u8 **in_aml_address, NATIVE_CHAR *name_string) { - u8 *aml_address = *in_aml_address; + char *aml_address = (void *) *in_aml_address; acpi_status status = AE_OK; u32 index; - NATIVE_CHAR char_buf[5]; + char char_buf[5]; ACPI_FUNCTION_TRACE ("Ex_name_segment"); @@ -170,17 +169,17 @@ ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n")); - for (index = 4; - (index > 0) && (acpi_ut_valid_acpi_character (*aml_address)); - index--) { - char_buf[4 - index] = *aml_address++; - ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", char_buf[4 - index])); + for (index = 0; + (index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_character (*aml_address)); + index++) { + char_buf[index] = *aml_address++; + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", char_buf[index])); } /* Valid name segment */ - if (0 == index) { + if (index == 4) { /* Found 4 valid characters */ char_buf[4] = '\0'; @@ -195,7 +194,7 @@ "No Name string - %s \n", char_buf)); } } - else if (4 == index) { + else if (index == 0) { /* * First character was not a valid name character, * so we are looking at something other than a name. @@ -213,7 +212,7 @@ *aml_address, aml_address)); } - *in_aml_address = aml_address; + *in_aml_address = (u8 *) aml_address; return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c --- a/drivers/acpi/executer/exoparg1.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/executer/exoparg1.c Sun Jun 2 18:44:58 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exoparg1 - AML execution - opcodes with 1 argument - * $Revision: 135 $ + * $Revision: 137 $ * *****************************************************************************/ @@ -212,7 +212,7 @@ ACPI_FUNCTION_TRACE_STR ("Ex_opcode_1A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); - /* Create a return object of type Integer for most opcodes */ + /* Examine the AML opcode */ switch (walk_state->opcode) { case AML_BIT_NOT_OP: @@ -222,156 +222,159 @@ case AML_TO_BCD_OP: case AML_COND_REF_OF_OP: + /* Create a return object of type Integer for these opcodes */ + return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; } - break; - } + switch (walk_state->opcode) { + case AML_BIT_NOT_OP: /* Not (Operand, Result) */ - /* Examine the AML opcode */ + return_desc->integer.value = ~operand[0]->integer.value; + break; - switch (walk_state->opcode) { - case AML_BIT_NOT_OP: /* Not (Operand, Result) */ + case AML_FIND_SET_LEFT_BIT_OP: /* Find_set_left_bit (Operand, Result) */ - return_desc->integer.value = ~operand[0]->integer.value; - break; + return_desc->integer.value = operand[0]->integer.value; + /* + * Acpi specification describes Integer type as a little + * endian unsigned value, so this boundary condition is valid. + */ + for (temp32 = 0; return_desc->integer.value && temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { + return_desc->integer.value >>= 1; + } - case AML_FIND_SET_LEFT_BIT_OP: /* Find_set_left_bit (Operand, Result) */ + return_desc->integer.value = temp32; + break; - return_desc->integer.value = operand[0]->integer.value; - /* - * Acpi specification describes Integer type as a little - * endian unsigned value, so this boundary condition is valid. - */ - for (temp32 = 0; return_desc->integer.value && temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { - return_desc->integer.value >>= 1; - } + case AML_FIND_SET_RIGHT_BIT_OP: /* Find_set_right_bit (Operand, Result) */ - return_desc->integer.value = temp32; - break; + return_desc->integer.value = operand[0]->integer.value; + /* + * The Acpi specification describes Integer type as a little + * endian unsigned value, so this boundary condition is valid. + */ + for (temp32 = 0; return_desc->integer.value && temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { + return_desc->integer.value <<= 1; + } - case AML_FIND_SET_RIGHT_BIT_OP: /* Find_set_right_bit (Operand, Result) */ + /* Since the bit position is one-based, subtract from 33 (65) */ - return_desc->integer.value = operand[0]->integer.value; + return_desc->integer.value = temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32; + break; - /* - * The Acpi specification describes Integer type as a little - * endian unsigned value, so this boundary condition is valid. - */ - for (temp32 = 0; return_desc->integer.value && temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { - return_desc->integer.value <<= 1; - } - /* Since the bit position is one-based, subtract from 33 (65) */ + case AML_FROM_BCD_OP: /* From_bcd (BCDValue, Result) */ - return_desc->integer.value = temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32; - break; + /* + * The 64-bit ACPI integer can hold 16 4-bit BCD integers + */ + return_desc->integer.value = 0; + for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { + /* Get one BCD digit */ + digit = (acpi_integer) ((operand[0]->integer.value >> (i * 4)) & 0xF); - case AML_FROM_BCD_OP: /* From_bcd (BCDValue, Result) */ + /* Check the range of the digit */ - /* - * The 64-bit ACPI integer can hold 16 4-bit BCD integers - */ - return_desc->integer.value = 0; - for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { - /* Get one BCD digit */ + if (digit > 9) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD digit too large: %d\n", + (u32) digit)); + status = AE_AML_NUMERIC_OVERFLOW; + goto cleanup; + } + + if (digit > 0) { + /* Sum into the result with the appropriate power of 10 */ + + for (j = 0; j < i; j++) { + digit *= 10; + } + + return_desc->integer.value += digit; + } + } + break; - digit = (acpi_integer) ((operand[0]->integer.value >> (i * 4)) & 0xF); - /* Check the range of the digit */ + case AML_TO_BCD_OP: /* To_bcd (Operand, Result) */ - if (digit > 9) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD digit too large: %d\n", - (u32) digit)); + if (operand[0]->integer.value > ACPI_MAX_BCD_VALUE) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD overflow: %8.8X%8.8X\n", + ACPI_HIDWORD(operand[0]->integer.value), + ACPI_LODWORD(operand[0]->integer.value))); status = AE_AML_NUMERIC_OVERFLOW; goto cleanup; } - if (digit > 0) { - /* Sum into the result with the appropriate power of 10 */ + return_desc->integer.value = 0; + for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { + /* Divide by nth factor of 10 */ + temp32 = 0; + digit = operand[0]->integer.value; for (j = 0; j < i; j++) { - digit *= 10; + (void) acpi_ut_short_divide (&digit, 10, &digit, &temp32); } - return_desc->integer.value += digit; + /* Create the BCD digit from the remainder above */ + + if (digit > 0) { + return_desc->integer.value += ((acpi_integer) temp32 << (i * 4)); + } } - } - break; + break; - case AML_TO_BCD_OP: /* To_bcd (Operand, Result) */ + case AML_COND_REF_OF_OP: /* Cond_ref_of (Source_object, Result) */ - if (operand[0]->integer.value > ACPI_MAX_BCD_VALUE) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "BCD overflow: %8.8X%8.8X\n", - ACPI_HIDWORD(operand[0]->integer.value), - ACPI_LODWORD(operand[0]->integer.value))); - status = AE_AML_NUMERIC_OVERFLOW; - goto cleanup; - } + /* + * This op is a little strange because the internal return value is + * different than the return value stored in the result descriptor + * (There are really two return values) + */ + if ((acpi_namespace_node *) operand[0] == acpi_gbl_root_node) { + /* + * This means that the object does not exist in the namespace, + * return FALSE + */ + return_desc->integer.value = 0; - return_desc->integer.value = 0; - for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { - /* Divide by nth factor of 10 */ - - temp32 = 0; - digit = operand[0]->integer.value; - for (j = 0; j < i; j++) { - acpi_ut_short_divide (&digit, 10, &digit, &temp32); + /* + * Must delete the result descriptor since there is no reference + * being returned + */ + acpi_ut_remove_reference (operand[1]); + goto cleanup; } - /* Create the BCD digit from the remainder above */ + /* Get the object reference and store it */ - if (digit > 0) { - return_desc->integer.value += ((acpi_integer) temp32 << (i * 4)); + status = acpi_ex_get_object_reference (operand[0], &return_desc2, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; } - } - break; + status = acpi_ex_store (return_desc2, operand[1], walk_state); - case AML_COND_REF_OF_OP: /* Cond_ref_of (Source_object, Result) */ + /* The object exists in the namespace, return TRUE */ - /* - * This op is a little strange because the internal return value is - * different than the return value stored in the result descriptor - * (There are really two return values) - */ - if ((acpi_namespace_node *) operand[0] == acpi_gbl_root_node) { - /* - * This means that the object does not exist in the namespace, - * return FALSE - */ - return_desc->integer.value = 0; - - /* - * Must delete the result descriptor since there is no reference - * being returned - */ - acpi_ut_remove_reference (operand[1]); + return_desc->integer.value = ACPI_INTEGER_MAX; goto cleanup; - } - /* Get the object reference and store it */ - status = acpi_ex_get_object_reference (operand[0], &return_desc2, walk_state); - if (ACPI_FAILURE (status)) { - goto cleanup; + default: + /* No other opcodes get here */ + break; } - - status = acpi_ex_store (return_desc2, operand[1], walk_state); - - /* The object exists in the namespace, return TRUE */ - - return_desc->integer.value = ACPI_INTEGER_MAX; - goto cleanup; + break; case AML_STORE_OP: /* Store (Source, Target) */ @@ -520,7 +523,7 @@ * can be either a NS Node or an internal object. */ return_desc = operand[0]; - if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) == ACPI_DESC_TYPE_INTERNAL) { + if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) == ACPI_DESC_TYPE_OPERAND) { /* Internal reference object - prevent deletion */ acpi_ut_add_reference (return_desc); @@ -628,6 +631,11 @@ case INTERNAL_TYPE_INDEX_FIELD: type = ACPI_TYPE_FIELD_UNIT; + break; + + default: + /* No change to Type required */ + break; } } @@ -722,8 +730,11 @@ /* Set Operand[0] to the value of the local/arg */ - acpi_ds_method_data_get_value (operand[0]->reference.opcode, - operand[0]->reference.offset, walk_state, &temp_desc); + status = acpi_ds_method_data_get_value (operand[0]->reference.opcode, + operand[0]->reference.offset, walk_state, &temp_desc); + if (ACPI_FAILURE (status)) { + goto cleanup; + } /* * Delete our reference to the input object and @@ -750,13 +761,15 @@ * 2) Dereference the node to an actual object. Could be a Field, so we nee * to resolve the node to a value. */ - status = acpi_ns_get_node_by_path (operand[0]->string.pointer, walk_state->scope_info->scope.node, - ACPI_NS_SEARCH_PARENT, (acpi_namespace_node **) &return_desc); + status = acpi_ns_get_node_by_path (operand[0]->string.pointer, + walk_state->scope_info->scope.node, ACPI_NS_SEARCH_PARENT, + ACPI_CAST_INDIRECT_PTR (acpi_namespace_node, &return_desc)); if (ACPI_FAILURE (status)) { goto cleanup; } - status = acpi_ex_resolve_node_to_value ((acpi_namespace_node **) &return_desc, walk_state); + status = acpi_ex_resolve_node_to_value ( + ACPI_CAST_INDIRECT_PTR (acpi_namespace_node, &return_desc), walk_state); goto cleanup; diff -Nru a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c --- a/drivers/acpi/executer/exoparg2.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/executer/exoparg2.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exoparg2 - AML execution - opcodes with 2 arguments - * $Revision: 105 $ + * $Revision: 106 $ * *****************************************************************************/ @@ -26,11 +26,9 @@ #include "acpi.h" #include "acparser.h" -#include "acnamesp.h" #include "acinterp.h" #include "acevents.h" #include "amlcode.h" -#include "acdispat.h" #define _COMPONENT ACPI_EXECUTER diff -Nru a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c --- a/drivers/acpi/executer/exoparg3.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/executer/exoparg3.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exoparg3 - AML execution - opcodes with 3 arguments - * $Revision: 9 $ + * $Revision: 13 $ * *****************************************************************************/ @@ -87,7 +87,7 @@ case AML_FATAL_OP: /* Fatal (Fatal_type Fatal_code Fatal_arg) */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Fatal_op: Type %x Code %x Arg %x <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", + "Fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", (u32) operand[0]->integer.value, (u32) operand[1]->integer.value, (u32) operand[2]->integer.value)); @@ -102,7 +102,7 @@ /* * Always signal the OS! */ - acpi_os_signal (ACPI_SIGNAL_FATAL, fatal); + status = acpi_os_signal (ACPI_SIGNAL_FATAL, fatal); /* Might return while OS is shutting down, just continue */ @@ -145,8 +145,8 @@ acpi_operand_object *return_desc = NULL; char *buffer; acpi_status status = AE_OK; - u32 index; - u32 length; + NATIVE_UINT index; + ACPI_SIZE length; ACPI_FUNCTION_TRACE_STR ("Ex_opcode_3A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); @@ -167,8 +167,8 @@ /* Get the Integer values from the objects */ - index = (u32) operand[1]->integer.value; - length = (u32) operand[2]->integer.value; + index = (NATIVE_UINT) operand[1]->integer.value; + length = (ACPI_SIZE) operand[2]->integer.value; /* * If the index is beyond the length of the String/Buffer, or if the @@ -180,12 +180,12 @@ if ((index + length) > operand[0]->string.length) { - length = operand[0]->string.length - index; + length = (ACPI_SIZE) operand[0]->string.length - index; } /* Allocate a new buffer for the String/Buffer */ - buffer = ACPI_MEM_CALLOCATE (length + 1); + buffer = ACPI_MEM_CALLOCATE ((ACPI_SIZE) length + 1); if (!buffer) { status = AE_NO_MEMORY; goto cleanup; @@ -199,7 +199,7 @@ /* Set the length of the new String/Buffer */ return_desc->string.pointer = buffer; - return_desc->string.length = length; + return_desc->string.length = (u32) length; } break; diff -Nru a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c --- a/drivers/acpi/executer/exprep.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/executer/exprep.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities - * $Revision: 115 $ + * $Revision: 117 $ * *****************************************************************************/ @@ -29,7 +29,6 @@ #include "acinterp.h" #include "amlcode.h" #include "acnamesp.h" -#include "acparser.h" #define _COMPONENT ACPI_EXECUTER @@ -57,16 +56,15 @@ u32 *return_byte_alignment) { u32 access; - u32 length; u8 byte_alignment; u8 bit_length; +/* u32 Length; */ ACPI_FUNCTION_NAME ("Ex_decode_field_access"); access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK); - length = obj_desc->common_field.bit_length; switch (access) { case AML_FIELD_ACCESS_ANY: @@ -86,6 +84,8 @@ /* Use the length to set the access type */ + length = obj_desc->common_field.bit_length; + if (length <= 8) { bit_length = 8; } @@ -135,7 +135,7 @@ /* Invalid field access type */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Unknown field access type %x\n", + "Unknown field access type %X\n", access)); return (0); } @@ -410,6 +410,10 @@ obj_desc->index_field.index_obj, obj_desc->index_field.data_obj)); break; + + default: + /* No other types should get here */ + break; } /* @@ -420,7 +424,7 @@ acpi_ns_get_type (info->field_node)); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "set Named_obj %p (%4.4s) val = %p\n", - info->field_node, (char *) &(info->field_node->name), obj_desc)); + info->field_node, info->field_node->name.ascii, obj_desc)); /* Remove local reference to the object */ diff -Nru a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c --- a/drivers/acpi/executer/exregion.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/executer/exregion.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exregion - ACPI default Op_region (address space) handlers - * $Revision: 74 $ + * $Revision: 79 $ * *****************************************************************************/ @@ -27,10 +27,6 @@ #include "acpi.h" #include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "achware.h" -#include "acevents.h" #define _COMPONENT ACPI_EXECUTER @@ -68,8 +64,10 @@ void *logical_addr_ptr = NULL; acpi_mem_space_context *mem_info = region_context; u32 length; - u32 window_size; - + ACPI_SIZE window_size; +#ifndef _HW_ALIGNMENT_SUPPORT + u32 remainder; +#endif ACPI_FUNCTION_TRACE ("Ex_system_memory_space_handler"); @@ -99,6 +97,18 @@ return_ACPI_STATUS (AE_AML_OPERAND_VALUE); } + +#ifndef _HW_ALIGNMENT_SUPPORT + /* + * Hardware does not support non-aligned data transfers, we must verify + * the request. + */ + (void) acpi_ut_short_divide ((acpi_integer *) &address, length, NULL, &remainder); + if (remainder != 0) { + return_ACPI_STATUS (AE_AML_ALIGNMENT); + } +#endif + /* * Does the request fit into the cached memory mapping? * Is 1) Address below the current mapping? OR @@ -122,7 +132,7 @@ * Don't attempt to map memory beyond the end of the region, and * constrain the maximum mapping size to something reasonable. */ - window_size = (u32) ((mem_info->address + mem_info->length) - address); + window_size = (ACPI_SIZE) ((mem_info->address + mem_info->length) - address); if (window_size > SYSMEM_REGION_WINDOW_SIZE) { window_size = SYSMEM_REGION_WINDOW_SIZE; } @@ -132,6 +142,8 @@ status = acpi_os_map_memory (address, window_size, (void **) &mem_info->mapped_logical_address); if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X%8.8X, size %X\n", + ACPI_HIDWORD (address), ACPI_LODWORD (address), (u32) window_size)); mem_info->mapped_length = 0; return_ACPI_STATUS (status); } @@ -153,27 +165,38 @@ "System_memory %d (%d width) Address=%8.8X%8.8X\n", function, bit_width, ACPI_HIDWORD (address), ACPI_LODWORD (address))); - /* Perform the memory read or write */ - + /* + * Perform the memory read or write + * + * Note: For machines that do not support non-aligned transfers, the target + * address was checked for alignment above. We do not attempt to break the + * transfer up into smaller (byte-size) chunks because the AML specifically + * asked for a transfer width that the hardware may require. + */ switch (function) { case ACPI_READ: *value = 0; switch (bit_width) { case 8: - *value = (u32)* (u8 *) logical_addr_ptr; + *value = (acpi_integer) *((u8 *) logical_addr_ptr); break; case 16: - ACPI_MOVE_UNALIGNED16_TO_16 (value, logical_addr_ptr); + *value = (acpi_integer) *((u16 *) logical_addr_ptr); break; case 32: - ACPI_MOVE_UNALIGNED32_TO_32 (value, logical_addr_ptr); + *value = (acpi_integer) *((u32 *) logical_addr_ptr); break; +#if ACPI_MACHINE_WIDTH != 16 case 64: - ACPI_MOVE_UNALIGNED64_TO_64 (value, logical_addr_ptr); + *value = (acpi_integer) *((u64 *) logical_addr_ptr); + break; +#endif + default: + /* Bit_width was already validated */ break; } break; @@ -186,15 +209,21 @@ break; case 16: - ACPI_MOVE_UNALIGNED16_TO_16 (logical_addr_ptr, value); + *(u16 *) logical_addr_ptr = (u16) *value; break; case 32: - ACPI_MOVE_UNALIGNED32_TO_32 (logical_addr_ptr, value); + *(u32 *) logical_addr_ptr = (u32) *value; break; +#if ACPI_MACHINE_WIDTH != 16 case 64: - ACPI_MOVE_UNALIGNED64_TO_64 (logical_addr_ptr, value); + *(u64 *) logical_addr_ptr = (u64) *value; + break; +#endif + + default: + /* Bit_width was already validated */ break; } break; @@ -316,7 +345,7 @@ * */ pci_id = (acpi_pci_id *) region_context; - pci_register = (u16) (ACPI_SIZE) address; + pci_register = (u16) (u32) address; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", @@ -469,6 +498,7 @@ break; case ACPI_WRITE: + default: return_ACPI_STATUS (AE_SUPPORT); } diff -Nru a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c --- a/drivers/acpi/executer/exresnte.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/executer/exresnte.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exresnte - AML Interpreter object resolution - * $Revision: 52 $ + * $Revision: 53 $ * *****************************************************************************/ @@ -27,12 +27,9 @@ #include "acpi.h" #include "amlcode.h" -#include "acparser.h" #include "acdispat.h" #include "acinterp.h" #include "acnamesp.h" -#include "actables.h" -#include "acevents.h" #define _COMPONENT ACPI_EXECUTER diff -Nru a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c --- a/drivers/acpi/executer/exresolv.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/executer/exresolv.c Sun Jun 2 18:44:57 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exresolv - AML Interpreter object resolution - * $Revision: 109 $ + * $Revision: 111 $ * *****************************************************************************/ @@ -27,12 +27,8 @@ #include "acpi.h" #include "amlcode.h" -#include "acparser.h" #include "acdispat.h" #include "acinterp.h" -#include "acnamesp.h" -#include "actables.h" -#include "acevents.h" #define _COMPONENT ACPI_EXECUTER @@ -75,7 +71,7 @@ * 1) A valid acpi_operand_object, or * 2) A acpi_namespace_node (Named_obj) */ - if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_INTERNAL) { + if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_OPERAND) { status = acpi_ex_resolve_object_to_value (stack_ptr, walk_state); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); @@ -87,7 +83,8 @@ * was called (i.e., we can't use an _else_ here.) */ if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_NAMED) { - status = acpi_ex_resolve_node_to_value ((acpi_namespace_node **) stack_ptr, + status = acpi_ex_resolve_node_to_value ( + ACPI_CAST_INDIRECT_PTR (acpi_namespace_node, stack_ptr), walk_state); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); @@ -216,6 +213,10 @@ case AML_REVISION_OP: obj_desc->integer.value = ACPI_CA_SUPPORT_LEVEL; + break; + + default: + /* No other opcodes can get here */ break; } diff -Nru a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c --- a/drivers/acpi/executer/exresop.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/executer/exresop.c Sun Jun 2 18:44:58 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exresop - AML Interpreter operand/object resolution - * $Revision: 48 $ + * $Revision: 50 $ * *****************************************************************************/ @@ -28,11 +28,8 @@ #include "acpi.h" #include "amlcode.h" #include "acparser.h" -#include "acdispat.h" #include "acinterp.h" #include "acnamesp.h" -#include "actables.h" -#include "acevents.h" #define _COMPONENT ACPI_EXECUTER @@ -168,7 +165,7 @@ break; - case ACPI_DESC_TYPE_INTERNAL: + case ACPI_DESC_TYPE_OPERAND: /* ACPI internal object */ @@ -243,7 +240,7 @@ switch (this_arg_type) { case ARGI_REF_OR_STRING: /* Can be a String or Reference */ - if ((ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_INTERNAL) && + if ((ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_OPERAND) && (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_STRING)) { /* * String found - the string references a named object and must be @@ -253,6 +250,7 @@ } /* Else not a string - fall through to the normal Reference case below */ + /*lint -fallthrough */ case ARGI_REFERENCE: /* References: */ case ARGI_INTEGER_REF: @@ -299,6 +297,10 @@ ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) { goto next_operand; } + break; + + default: + /* All cases covered above */ break; } diff -Nru a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c --- a/drivers/acpi/executer/exstore.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/executer/exstore.c Sun Jun 2 18:44:57 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exstore - AML Interpreter object store support - * $Revision: 163 $ + * $Revision: 164 $ * *****************************************************************************/ @@ -26,12 +26,10 @@ #include "acpi.h" -#include "acparser.h" #include "acdispat.h" #include "acinterp.h" #include "amlcode.h" #include "acnamesp.h" -#include "actables.h" #define _COMPONENT ACPI_EXECUTER @@ -328,7 +326,7 @@ case ACPI_TYPE_STRING: - value = source_desc->string.pointer[0]; + value = (u8) source_desc->string.pointer[0]; break; default: diff -Nru a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c --- a/drivers/acpi/executer/exstoren.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/executer/exstoren.c Sun Jun 2 18:44:56 2002 @@ -3,7 +3,7 @@ * * Module Name: exstoren - AML Interpreter object store support, * Store to Node (namespace object) - * $Revision: 47 $ + * $Revision: 48 $ * *****************************************************************************/ @@ -27,12 +27,7 @@ #include "acpi.h" -#include "acparser.h" -#include "acdispat.h" #include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "actables.h" #define _COMPONENT ACPI_EXECUTER diff -Nru a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c --- a/drivers/acpi/executer/exstorob.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/executer/exstorob.c Sun Jun 2 18:44:57 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exstorob - AML Interpreter object store support, store to object - * $Revision: 42 $ + * $Revision: 44 $ * *****************************************************************************/ @@ -26,12 +26,7 @@ #include "acpi.h" -#include "acparser.h" -#include "acdispat.h" #include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "actables.h" #define _COMPONENT ACPI_EXECUTER @@ -166,7 +161,7 @@ ACPI_MEM_FREE (target_desc->string.pointer); } - target_desc->string.pointer = ACPI_MEM_ALLOCATE (length + 1); + target_desc->string.pointer = ACPI_MEM_ALLOCATE ((ACPI_SIZE) length + 1); if (!target_desc->string.pointer) { return (AE_NO_MEMORY); } diff -Nru a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c --- a/drivers/acpi/executer/exsystem.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/executer/exsystem.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exsystem - Interface to OS services - * $Revision: 71 $ + * $Revision: 73 $ * *****************************************************************************/ @@ -27,8 +27,6 @@ #include "acpi.h" #include "acinterp.h" -#include "acnamesp.h" -#include "achware.h" #include "acevents.h" #define _COMPONENT ACPI_EXECUTER @@ -246,8 +244,8 @@ * Support for the _GL_ Mutex object -- release the global lock */ if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) { - acpi_ev_release_global_lock (); - return_ACPI_STATUS (AE_OK); + status = acpi_ev_release_global_lock (); + return_ACPI_STATUS (status); } status = acpi_os_signal_semaphore (obj_desc->mutex.semaphore, 1); @@ -350,7 +348,7 @@ */ status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore); if (ACPI_SUCCESS (status)) { - acpi_os_delete_semaphore (obj_desc->event.semaphore); + (void) acpi_os_delete_semaphore (obj_desc->event.semaphore); obj_desc->event.semaphore = temp_semaphore; } diff -Nru a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c --- a/drivers/acpi/executer/exutils.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/executer/exutils.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exutils - interpreter/scanner utilities - * $Revision: 93 $ + * $Revision: 98 $ * *****************************************************************************/ @@ -42,12 +42,9 @@ #define DEFINE_AML_GLOBALS #include "acpi.h" -#include "acparser.h" #include "acinterp.h" #include "amlcode.h" -#include "acnamesp.h" #include "acevents.h" -#include "acparser.h" #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME ("exutils") @@ -74,7 +71,7 @@ status = acpi_ut_acquire_mutex (ACPI_MTX_EXECUTE); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("Fatal - Could not acquire interpreter lock\n")); + ACPI_REPORT_ERROR (("Could not acquire interpreter mutex\n")); } return_ACPI_STATUS (status); @@ -111,6 +108,9 @@ status = acpi_ut_release_mutex (ACPI_MTX_EXECUTE); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not release interpreter mutex\n")); + } return_VOID; } @@ -177,7 +177,7 @@ return; } - if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { + if (acpi_gbl_integer_byte_width == 4) { /* * We are running a method that exists in a 32-bit ACPI table. * Truncate the value to 32 bits by zeroing out the upper 32-bit field @@ -245,10 +245,12 @@ * ******************************************************************************/ -acpi_status +void acpi_ex_release_global_lock ( u8 locked_by_me) { + acpi_status status; + ACPI_FUNCTION_TRACE ("Ex_release_global_lock"); @@ -258,10 +260,13 @@ if (locked_by_me) { /* OK, now release the lock */ - acpi_ev_release_global_lock (); - } + status = acpi_ev_release_global_lock (); + if (ACPI_FAILURE (status)) { + /* Report the error, but there isn't much else we can do */ - return_ACPI_STATUS (AE_OK); + ACPI_REPORT_ERROR (("Could not release ACPI Global Lock\n")); + } + } } @@ -281,22 +286,24 @@ acpi_integer value, u32 base) { - u32 num_digits = 0; + u32 num_digits; + acpi_integer current_value; + acpi_integer quotient; ACPI_FUNCTION_TRACE ("Ex_digits_needed"); - if (base < 1) { - ACPI_REPORT_ERROR (("Ex_digits_needed: Internal error - Invalid base\n")); - } - else { - /* - * acpi_integer is unsigned, which is why we don't worry about a '-' - */ - for (num_digits = 1; - (acpi_ut_short_divide (&value, base, &value, NULL)); - ++num_digits) { ; } + /* + * acpi_integer is unsigned, so we don't worry about a '-' + */ + current_value = value; + num_digits = 0; + + while (current_value) { + (void) acpi_ut_short_divide (¤t_value, base, "ient, NULL); + num_digits++; + current_value = quotient; } return_VALUE (num_digits); @@ -305,45 +312,6 @@ /******************************************************************************* * - * FUNCTION: ntohl - * - * PARAMETERS: Value - Value to be converted - * - * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes) - * - ******************************************************************************/ - -static u32 -_ntohl ( - u32 value) -{ - union { - u32 value; - u8 bytes[4]; - } out; - - union { - u32 value; - u8 bytes[4]; - } in; - - - ACPI_FUNCTION_ENTRY (); - - - in.value = value; - - out.bytes[0] = in.bytes[3]; - out.bytes[1] = in.bytes[2]; - out.bytes[2] = in.bytes[1]; - out.bytes[3] = in.bytes[0]; - - return (out.value); -} - - -/******************************************************************************* - * * FUNCTION: Acpi_ex_eisa_id_to_string * * PARAMETERS: Numeric_id - EISA ID to be converted @@ -353,31 +321,29 @@ * ******************************************************************************/ -acpi_status +void acpi_ex_eisa_id_to_string ( u32 numeric_id, NATIVE_CHAR *out_string) { - u32 id; + u32 eisa_id; ACPI_FUNCTION_ENTRY (); - /* swap to big-endian to get contiguous bits */ + /* Swap ID to big-endian to get contiguous bits */ - id = _ntohl (numeric_id); + eisa_id = acpi_ut_dword_byte_swap (numeric_id); - out_string[0] = (char) ('@' + ((id >> 26) & 0x1f)); - out_string[1] = (char) ('@' + ((id >> 21) & 0x1f)); - out_string[2] = (char) ('@' + ((id >> 16) & 0x1f)); - out_string[3] = acpi_ut_hex_to_ascii_char (id, 12); - out_string[4] = acpi_ut_hex_to_ascii_char (id, 8); - out_string[5] = acpi_ut_hex_to_ascii_char (id, 4); - out_string[6] = acpi_ut_hex_to_ascii_char (id, 0); + out_string[0] = (char) ('@' + ((eisa_id >> 26) & 0x1f)); + out_string[1] = (char) ('@' + ((eisa_id >> 21) & 0x1f)); + out_string[2] = (char) ('@' + ((eisa_id >> 16) & 0x1f)); + out_string[3] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 12); + out_string[4] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 8); + out_string[5] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 4); + out_string[6] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 0); out_string[7] = 0; - - return (AE_OK); } @@ -392,7 +358,7 @@ * ******************************************************************************/ -acpi_status +void acpi_ex_unsigned_integer_to_string ( acpi_integer value, NATIVE_CHAR *out_string) @@ -400,6 +366,7 @@ u32 count; u32 digits_needed; u32 remainder; + acpi_integer quotient; ACPI_FUNCTION_ENTRY (); @@ -409,11 +376,10 @@ out_string[digits_needed] = 0; for (count = digits_needed; count > 0; count--) { - acpi_ut_short_divide (&value, 10, &value, &remainder); - out_string[count-1] = (NATIVE_CHAR) ('0' + remainder); + (void) acpi_ut_short_divide (&value, 10, "ient, &remainder); + out_string[count-1] = (NATIVE_CHAR) ('0' + remainder);\ + value = quotient; } - - return (AE_OK); } diff -Nru a/drivers/acpi/fan.c b/drivers/acpi/fan.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/fan.c Sun Jun 2 18:44:56 2002 @@ -0,0 +1,299 @@ +/* + * acpi_fan.c - ACPI Fan Driver ($Revision: 28 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_FAN_COMPONENT +ACPI_MODULE_NAME ("acpi_fan") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + + +int acpi_fan_add (struct acpi_device *device); +int acpi_fan_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_fan_driver = { + name: ACPI_FAN_DRIVER_NAME, + class: ACPI_FAN_CLASS, + ids: ACPI_FAN_HID, + ops: { + add: acpi_fan_add, + remove: acpi_fan_remove, + }, +}; + +struct acpi_fan { + acpi_handle handle; +}; + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +struct proc_dir_entry *acpi_fan_dir = NULL; + + +static int +acpi_fan_read_state ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_fan *fan = (struct acpi_fan *) data; + char *p = page; + int len = 0; + int state = 0; + + ACPI_FUNCTION_TRACE("acpi_fan_read_state"); + + if (!fan || (off != 0)) + goto end; + + if (acpi_bus_get_power(fan->handle, &state)) + goto end; + + p += sprintf(p, "status: %s\n", + !state?"on":"off"); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_fan_write_state ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + struct acpi_fan *fan = (struct acpi_fan *) data; + char state_string[12] = {'\0'}; + + ACPI_FUNCTION_TRACE("acpi_fan_write_state"); + + if (!fan || (count > sizeof(state_string) - 1)) + return_VALUE(-EINVAL); + + if (copy_from_user(state_string, buffer, count)) + return_VALUE(-EFAULT); + + state_string[count] = '\0'; + + result = acpi_bus_set_power(fan->handle, + simple_strtoul(state_string, NULL, 0)); + if (result) + return_VALUE(result); + + return_VALUE(count); +} + + +static int +acpi_fan_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_fan_add_fs"); + + if (!device) + return_VALUE(-EINVAL); + + if (!acpi_fan_dir) { + acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir); + if (!acpi_fan_dir) + return_VALUE(-ENODEV); + } + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_fan_dir); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + } + + /* 'status' [R/W] */ + entry = create_proc_entry(ACPI_FAN_FILE_STATE, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_FAN_FILE_STATE)); + else { + entry->read_proc = acpi_fan_read_state; + entry->write_proc = acpi_fan_write_state; + entry->data = acpi_driver_data(device); + } + + return_VALUE(0); +} + + +static int +acpi_fan_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_fan_remove_fs"); + + if (!acpi_fan_dir) + return_VALUE(-ENODEV); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_fan_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +int +acpi_fan_add ( + struct acpi_device *device) +{ + int result = 0; + struct acpi_fan *fan = NULL; + int state = 0; + + ACPI_FUNCTION_TRACE("acpi_fan_add"); + + if (!device) + return_VALUE(-EINVAL); + + fan = kmalloc(sizeof(struct acpi_fan), GFP_KERNEL); + if (!fan) + return_VALUE(-ENOMEM); + memset(fan, 0, sizeof(struct acpi_fan)); + + fan->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_FAN_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_FAN_CLASS); + acpi_driver_data(device) = fan; + + result = acpi_bus_get_power(fan->handle, &state); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error reading power state\n")); + goto end; + } + + result = acpi_fan_add_fs(device); + if (result) + goto end; + + printk(KERN_INFO PREFIX "%s [%s] (%s)\n", + acpi_device_name(device), acpi_device_bid(device), + !device->power.state?"on":"off"); + +end: + if (result) + kfree(fan); + + return_VALUE(result); +} + + +int +acpi_fan_remove ( + struct acpi_device *device, + int type) +{ + struct acpi_fan *fan = NULL; + + ACPI_FUNCTION_TRACE("acpi_fan_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + fan = (struct acpi_fan *) acpi_driver_data(device); + + acpi_fan_remove_fs(device); + + kfree(fan); + + return_VALUE(0); +} + + +int __init +acpi_fan_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_fan_init"); + + result = acpi_bus_register_driver(&acpi_fan_driver); + if (result < 0) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + + +void __exit +acpi_fan_exit (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_fan_exit"); + + result = acpi_bus_unregister_driver(&acpi_fan_driver); + if (!result) + remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir); + + return_VOID; +} + + +module_init(acpi_fan_init); +module_exit(acpi_fan_exit); + diff -Nru a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c --- a/drivers/acpi/hardware/hwacpi.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/hardware/hwacpi.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface - * $Revision: 53 $ + * $Revision: 58 $ * *****************************************************************************/ @@ -26,7 +26,6 @@ #include "acpi.h" -#include "achware.h" #define _COMPONENT ACPI_HARDWARE @@ -91,35 +90,57 @@ u32 mode) { - acpi_status status = AE_NO_HARDWARE_RESPONSE; + acpi_status status; + u32 retry; ACPI_FUNCTION_TRACE ("Hw_set_mode"); + switch (mode) { + case ACPI_SYS_MODE_ACPI: - if (mode == ACPI_SYS_MODE_ACPI) { /* BIOS should have disabled ALL fixed and GP events */ - acpi_os_write_port (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_enable, 8); + status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, + (acpi_integer) acpi_gbl_FADT->acpi_enable, 8); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI mode\n")); - } - else if (mode == ACPI_SYS_MODE_LEGACY) { + break; + + case ACPI_SYS_MODE_LEGACY: + /* * BIOS should clear all fixed status bits and restore fixed event * enable bits to default */ - acpi_os_write_port (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_disable, 8); + status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, + (acpi_integer) acpi_gbl_FADT->acpi_disable, 8); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable Legacy (non-ACPI) mode\n")); - } + break; - /* Give the platform some time to react */ + default: + return_ACPI_STATUS (AE_BAD_PARAMETER); + } - acpi_os_stall (20000); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - if (acpi_hw_get_mode () == mode) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n", mode)); - status = AE_OK; + /* + * Some hardware takes a LONG time to switch modes. Give them 3 sec to + * do so, but allow faster systems to proceed more quickly. + */ + retry = 3000; + while (retry) { + status = AE_NO_HARDWARE_RESPONSE; + + if (acpi_hw_get_mode() == mode) { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n", mode)); + status = AE_OK; + break; + } + acpi_os_stall(1000); + retry--; } return_ACPI_STATUS (status); @@ -142,11 +163,18 @@ u32 acpi_hw_get_mode (void) { + acpi_status status; + u32 value; + ACPI_FUNCTION_TRACE ("Hw_get_mode"); + status = acpi_get_register (ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_VALUE (ACPI_SYS_MODE_LEGACY); + } - if (acpi_hw_bit_register_read (ACPI_BITREG_SCI_ENABLE, ACPI_MTX_LOCK)) { + if (value) { return_VALUE (ACPI_SYS_MODE_ACPI); } else { diff -Nru a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c --- a/drivers/acpi/hardware/hwgpe.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/hardware/hwgpe.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: hwgpe - Low level GPE enable/disable/clear functions - * $Revision: 40 $ + * $Revision: 41 $ * *****************************************************************************/ @@ -25,8 +25,6 @@ */ #include "acpi.h" -#include "achware.h" -#include "acnamesp.h" #include "acevents.h" #define _COMPONENT ACPI_HARDWARE @@ -45,7 +43,7 @@ * ******************************************************************************/ -u32 +u8 acpi_hw_get_gpe_bit_mask ( u32 gpe_number) { @@ -65,13 +63,14 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_enable_gpe ( u32 gpe_number) { u32 in_byte; u32 register_index; - u32 bit_mask; + u8 bit_mask; + acpi_status status; ACPI_FUNCTION_ENTRY (); @@ -89,10 +88,16 @@ * Read the current value of the register, set the appropriate bit * to enable the GPE, and write out the new register. */ - in_byte = acpi_hw_low_level_read (8, - &acpi_gbl_gpe_register_info[register_index].enable_address, 0); - acpi_hw_low_level_write (8, (in_byte | bit_mask), - &acpi_gbl_gpe_register_info[register_index].enable_address, 0); + status = acpi_hw_low_level_read (8, &in_byte, + &acpi_gbl_gpe_register_info[register_index].enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_hw_low_level_write (8, (in_byte | bit_mask), + &acpi_gbl_gpe_register_info[register_index].enable_address, 0); + + return (status); } @@ -114,7 +119,7 @@ u32 gpe_number) { u32 register_index; - u32 bit_mask; + u8 bit_mask; ACPI_FUNCTION_ENTRY (); @@ -147,13 +152,14 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_disable_gpe ( u32 gpe_number) { u32 in_byte; u32 register_index; - u32 bit_mask; + u8 bit_mask; + acpi_status status; ACPI_FUNCTION_ENTRY (); @@ -171,12 +177,20 @@ * Read the current value of the register, clear the appropriate bit, * and write out the new register value to disable the GPE. */ - in_byte = acpi_hw_low_level_read (8, - &acpi_gbl_gpe_register_info[register_index].enable_address, 0); - acpi_hw_low_level_write (8, (in_byte & ~bit_mask), - &acpi_gbl_gpe_register_info[register_index].enable_address, 0); + status = acpi_hw_low_level_read (8, &in_byte, + &acpi_gbl_gpe_register_info[register_index].enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_hw_low_level_write (8, (in_byte & ~bit_mask), + &acpi_gbl_gpe_register_info[register_index].enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } acpi_hw_disable_gpe_for_wakeup(gpe_number); + return (AE_OK); } @@ -198,7 +212,7 @@ u32 gpe_number) { u32 register_index; - u32 bit_mask; + u8 bit_mask; ACPI_FUNCTION_ENTRY (); @@ -231,12 +245,13 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_clear_gpe ( u32 gpe_number) { u32 register_index; - u32 bit_mask; + u8 bit_mask; + acpi_status status; ACPI_FUNCTION_ENTRY (); @@ -254,8 +269,10 @@ * Write a one to the appropriate bit in the status register to * clear this GPE. */ - acpi_hw_low_level_write (8, bit_mask, - &acpi_gbl_gpe_register_info[register_index].status_address, 0); + status = acpi_hw_low_level_write (8, bit_mask, + &acpi_gbl_gpe_register_info[register_index].status_address, 0); + + return (status); } @@ -271,22 +288,23 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_get_gpe_status ( u32 gpe_number, acpi_event_status *event_status) { u32 in_byte = 0; u32 register_index = 0; - u32 bit_mask = 0; + u8 bit_mask = 0; ACPI_GPE_REGISTER_INFO *gpe_register_info; + acpi_status status; ACPI_FUNCTION_ENTRY (); if (!event_status) { - return; + return (AE_BAD_PARAMETER); } (*event_status) = 0; @@ -302,7 +320,11 @@ /* GPE Enabled? */ - in_byte = acpi_hw_low_level_read (8, &gpe_register_info->enable_address, 0); + status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } + if (bit_mask & in_byte) { (*event_status) |= ACPI_EVENT_FLAG_ENABLED; } @@ -315,10 +337,15 @@ /* GPE active (set)? */ - in_byte = acpi_hw_low_level_read (8, &gpe_register_info->status_address, 0); + status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } + if (bit_mask & in_byte) { (*event_status) |= ACPI_EVENT_FLAG_SET; } + return (AE_OK); } @@ -338,12 +365,14 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_disable_non_wakeup_gpes ( void) { u32 i; ACPI_GPE_REGISTER_INFO *gpe_register_info; + u32 in_value; + acpi_status status; ACPI_FUNCTION_ENTRY (); @@ -356,15 +385,24 @@ * Read the enabled status of all GPEs. We * will be using it to restore all the GPEs later. */ - gpe_register_info->enable = (u8) acpi_hw_low_level_read (8, + status = acpi_hw_low_level_read (8, &in_value, &gpe_register_info->enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } + + gpe_register_info->enable = (u8) in_value; /* * Disable all GPEs except wakeup GPEs. */ - acpi_hw_low_level_write (8, gpe_register_info->wake_enable, + status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable, &gpe_register_info->enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } } + return (AE_OK); } @@ -380,12 +418,13 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_enable_non_wakeup_gpes ( void) { u32 i; ACPI_GPE_REGISTER_INFO *gpe_register_info; + acpi_status status; ACPI_FUNCTION_ENTRY (); @@ -398,7 +437,11 @@ * We previously stored the enabled status of all GPEs. * Blast them back in. */ - acpi_hw_low_level_write (8, gpe_register_info->enable, & - gpe_register_info->enable_address, 0); + status = acpi_hw_low_level_write (8, gpe_register_info->enable, + &gpe_register_info->enable_address, 0); + if (ACPI_FAILURE (status)) { + return (status); + } } + return (AE_OK); } diff -Nru a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c --- a/drivers/acpi/hardware/hwregs.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/hardware/hwregs.c Sun Jun 2 18:44:57 2002 @@ -3,7 +3,7 @@ * * Module Name: hwregs - Read/write access functions for the various ACPI * control and status registers. - * $Revision: 121 $ + * $Revision: 130 $ * ******************************************************************************/ @@ -27,7 +27,6 @@ #include "acpi.h" -#include "achware.h" #include "acnamesp.h" #define _COMPONENT ACPI_HARDWARE @@ -46,10 +45,10 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_clear_acpi_status (void) { - NATIVE_UINT i; + NATIVE_UINT_MAX32 i; NATIVE_UINT gpe_block; acpi_status status; @@ -64,36 +63,46 @@ status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); if (ACPI_FAILURE (status)) { - return_VOID; + return_ACPI_STATUS (status); } - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, - ACPI_BITMASK_ALL_FIXED_STATUS); + status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, + ACPI_BITMASK_ALL_FIXED_STATUS); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } /* Clear the fixed events */ if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address)) { - acpi_hw_low_level_write (16, ACPI_BITMASK_ALL_FIXED_STATUS, - &acpi_gbl_FADT->Xpm1b_evt_blk, 0); + status = acpi_hw_low_level_write (16, ACPI_BITMASK_ALL_FIXED_STATUS, + &acpi_gbl_FADT->Xpm1b_evt_blk, 0); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } } /* Clear the GPE Bits */ for (gpe_block = 0; gpe_block < ACPI_MAX_GPE_BLOCKS; gpe_block++) { for (i = 0; i < acpi_gbl_gpe_block_info[gpe_block].register_count; i++) { - acpi_hw_low_level_write (8, 0xFF, - acpi_gbl_gpe_block_info[gpe_block].block_address, i); + status = acpi_hw_low_level_write (8, 0xFF, + acpi_gbl_gpe_block_info[gpe_block].block_address, i); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } } } +unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE); - return_VOID; + return_ACPI_STATUS (status); } /******************************************************************************* * - * FUNCTION: Acpi_hw_get_sleep_type_data + * FUNCTION: Acpi_get_sleep_type_data * * PARAMETERS: Sleep_state - Numeric sleep state * *Sleep_type_a - Where SLP_TYPa is returned @@ -107,7 +116,7 @@ ******************************************************************************/ acpi_status -acpi_hw_get_sleep_type_data ( +acpi_get_sleep_type_data ( u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) @@ -116,7 +125,7 @@ acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE ("Hw_get_sleep_type_data"); + ACPI_FUNCTION_TRACE ("Acpi_get_sleep_type_data"); /* @@ -213,7 +222,7 @@ /******************************************************************************* * - * FUNCTION: Acpi_hw_bit_register_read + * FUNCTION: Acpi_get_register * * PARAMETERS: Register_id - index of ACPI Register to access * Use_lock - Lock the hardware @@ -225,24 +234,20 @@ * ******************************************************************************/ -u32 -acpi_hw_bit_register_read ( +acpi_status +acpi_get_register ( u32 register_id, + u32 *return_value, u32 flags) { u32 register_value = 0; ACPI_BIT_REGISTER_INFO *bit_reg_info; + acpi_status status; - ACPI_FUNCTION_TRACE ("Hw_bit_register_read"); + ACPI_FUNCTION_TRACE ("Acpi_get_register"); - if (flags & ACPI_MTX_LOCK) { - if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE))) { - return_VALUE (0); - } - } - /* Get the info structure corresponding to the requested ACPI Register */ bit_reg_info = acpi_hw_get_bit_register_info (register_id); @@ -250,66 +255,86 @@ return_ACPI_STATUS (AE_BAD_PARAMETER); } - register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, bit_reg_info->parent_register); + if (flags & ACPI_MTX_LOCK) { + status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + + status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, + bit_reg_info->parent_register, ®ister_value); if (flags & ACPI_MTX_LOCK) { (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE); } - /* Normalize the value that was read */ + if (ACPI_SUCCESS (status)) { + /* Normalize the value that was read */ - register_value = ((register_value & bit_reg_info->access_bit_mask) >> bit_reg_info->bit_position); + register_value = ((register_value & bit_reg_info->access_bit_mask) + >> bit_reg_info->bit_position); - ACPI_DEBUG_PRINT ((ACPI_DB_IO, "ACPI Register_read: got %X\n", register_value)); - return_VALUE (register_value); + *return_value = register_value; + + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %X\n", register_value)); + } + + return_ACPI_STATUS (status); } /******************************************************************************* * - * FUNCTION: Acpi_hw_bit_register_write + * FUNCTION: Acpi_set_register * * PARAMETERS: Register_id - ID of ACPI Bit_register to access * Value - (only used on write) value to write to the * Register, NOT pre-normalized to the bit pos. * Flags - Lock the hardware or not * - * RETURN: Value written to from specified Register. This value - * is shifted all the way right. + * RETURN: None * * DESCRIPTION: ACPI Bit Register write function. * ******************************************************************************/ -u32 -acpi_hw_bit_register_write ( +acpi_status +acpi_set_register ( u32 register_id, u32 value, u32 flags) { u32 register_value = 0; ACPI_BIT_REGISTER_INFO *bit_reg_info; + acpi_status status; - ACPI_FUNCTION_TRACE_U32 ("Hw_bit_register_write", register_id); + ACPI_FUNCTION_TRACE_U32 ("Acpi_set_register", register_id); - if (flags & ACPI_MTX_LOCK) { - if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE))) { - return_VALUE (0); - } - } - /* Get the info structure corresponding to the requested ACPI Register */ bit_reg_info = acpi_hw_get_bit_register_info (register_id); if (!bit_reg_info) { + ACPI_REPORT_ERROR (("Bad ACPI HW Register_id: %X\n", register_id)); return_ACPI_STATUS (AE_BAD_PARAMETER); } + if (flags & ACPI_MTX_LOCK) { + status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + /* Always do a register read first so we can insert the new bits */ - register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, bit_reg_info->parent_register); + status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, + bit_reg_info->parent_register, ®ister_value); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } /* * Decode the Register ID @@ -327,10 +352,11 @@ * information is the single bit we're interested in, all others should * be written as 0 so they will be left unchanged */ - value = ACPI_REGISTER_PREPARE_BITS (value, bit_reg_info->bit_position, bit_reg_info->access_bit_mask); + value = ACPI_REGISTER_PREPARE_BITS (value, + bit_reg_info->bit_position, bit_reg_info->access_bit_mask); if (value) { - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, - (u16) value); + status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1_STATUS, (u16) value); register_value = 0; } break; @@ -338,9 +364,11 @@ case ACPI_REGISTER_PM1_ENABLE: - ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, bit_reg_info->access_bit_mask, value); + ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, + bit_reg_info->access_bit_mask, value); - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE, (u16) register_value); + status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1_ENABLE, (u16) register_value); break; @@ -353,29 +381,36 @@ */ ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", register_value)); - ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, bit_reg_info->access_bit_mask, value); + ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, + bit_reg_info->access_bit_mask, value); - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id, + status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id, (u16) register_value); break; case ACPI_REGISTER_PM2_CONTROL: - register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM2_CONTROL); + status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM2_CONTROL, ®ister_value); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n", - register_value, ACPI_HIDWORD (acpi_gbl_FADT->Xpm2_cnt_blk.address), - ACPI_LODWORD (acpi_gbl_FADT->Xpm2_cnt_blk.address))); + register_value, + ACPI_HIDWORD (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address)), + ACPI_LODWORD (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address)))); - ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, bit_reg_info->access_bit_mask, value); + ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, + bit_reg_info->access_bit_mask, value); - ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n", + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n", register_value, - ACPI_HIDWORD (acpi_gbl_FADT->Xpm2_cnt_blk.address), - ACPI_LODWORD (acpi_gbl_FADT->Xpm2_cnt_blk.address))); + ACPI_HIDWORD (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address)), + ACPI_LODWORD (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address)))); - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, + status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM2_CONTROL, (u8) (register_value)); break; @@ -384,16 +419,19 @@ break; } + +unlock_and_exit: + if (flags & ACPI_MTX_LOCK) { (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE); } /* Normalize the value that was read */ - register_value = ((register_value & bit_reg_info->access_bit_mask) >> bit_reg_info->bit_position); + ACPI_DEBUG_EXEC (register_value = ((register_value & bit_reg_info->access_bit_mask) >> bit_reg_info->bit_position)); - ACPI_DEBUG_PRINT ((ACPI_DB_IO, "ACPI Register_write actual %X\n", register_value)); - return_VALUE (register_value); + ACPI_DEBUG_PRINT ((ACPI_DB_IO, "ACPI Register Write actual %X\n", register_value)); + return_ACPI_STATUS (status); } @@ -411,73 +449,98 @@ * ******************************************************************************/ -u32 +acpi_status acpi_hw_register_read ( u8 use_lock, - u32 register_id) + u32 register_id, + u32 *return_value) { - u32 value = 0; + u32 value1 = 0; + u32 value2 = 0; u32 bank_offset; + acpi_status status; ACPI_FUNCTION_TRACE ("Hw_register_read"); if (ACPI_MTX_LOCK == use_lock) { - if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE))) { - return_VALUE (0); + status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } } switch (register_id) { case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ - value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, 0); - value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, 0); + status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->Xpm1a_evt_blk, 0); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + + status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->Xpm1b_evt_blk, 0); + value1 |= value2; break; case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access*/ bank_offset = ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len); - value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset); - value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset); + status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + + status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset); + value1 |= value2; break; case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ - value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); - value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); + status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + + status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); + value1 |= value2; break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xpm2_cnt_blk, 0); + status = acpi_hw_low_level_read (8, &value1, &acpi_gbl_FADT->Xpm2_cnt_blk, 0); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - value = acpi_hw_low_level_read (32, &acpi_gbl_FADT->Xpm_tmr_blk, 0); + status = acpi_hw_low_level_read (32, &value1, &acpi_gbl_FADT->Xpm_tmr_blk, 0); break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ - acpi_os_read_port (acpi_gbl_FADT->smi_cmd, &value, 8); + status = acpi_os_read_port (acpi_gbl_FADT->smi_cmd, &value1, 8); break; default: - /* Value will be returned as 0 */ + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Register ID: %X\n", register_id)); + status = AE_BAD_PARAMETER; break; } +unlock_and_exit: if (ACPI_MTX_LOCK == use_lock) { (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE); } - return_VALUE (value); + if (ACPI_SUCCESS (status)) { + *return_value = value1; + } + + return_ACPI_STATUS (status); } @@ -495,68 +558,82 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_register_write ( u8 use_lock, u32 register_id, u32 value) { u32 bank_offset; + acpi_status status; ACPI_FUNCTION_TRACE ("Hw_register_write"); if (ACPI_MTX_LOCK == use_lock) { - if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE))) { - return_VOID; + status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } } switch (register_id) { case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, 0); - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, 0); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, 0); break; case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access*/ bank_offset = ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len); - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset); - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset); break; case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); break; case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); break; case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xpm2_cnt_blk, 0); + status = acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xpm2_cnt_blk, 0); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->Xpm_tmr_blk, 0); + status = acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->Xpm_tmr_blk, 0); break; @@ -564,20 +641,21 @@ /* SMI_CMD is currently always in IO space */ - acpi_os_write_port (acpi_gbl_FADT->smi_cmd, value, 8); + status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, (acpi_integer) value, 8); break; default: - value = 0; + status = AE_BAD_PARAMETER; break; } +unlock_and_exit: if (ACPI_MTX_LOCK == use_lock) { (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE); } - return_VOID; + return_ACPI_STATUS (status); } @@ -595,30 +673,33 @@ * ******************************************************************************/ -u32 +acpi_status acpi_hw_low_level_read ( u32 width, + u32 *value, acpi_generic_address *reg, u32 offset) { - u32 value = 0; ACPI_PHYSICAL_ADDRESS mem_address; ACPI_IO_ADDRESS io_address; acpi_pci_id pci_id; u16 pci_register; + acpi_status status; - ACPI_FUNCTION_ENTRY (); + ACPI_FUNCTION_NAME ("Hw_low_level_read"); /* * Must have a valid pointer to a GAS structure, and - * a non-zero address within + * a non-zero address within. However, don't return an error + * because the PM1A/B code must not fail if B isn't present. */ if ((!reg) || (!ACPI_VALID_ADDRESS (reg->address))) { - return 0; + return (AE_OK); } + *value = 0; /* * Three address spaces supported: @@ -627,17 +708,19 @@ switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: - mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); + mem_address = (ACPI_GET_ADDRESS (reg->address) + + (ACPI_PHYSICAL_ADDRESS) offset); - acpi_os_read_memory (mem_address, &value, width); + status = acpi_os_read_memory (mem_address, value, width); break; case ACPI_ADR_SPACE_SYSTEM_IO: - io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); + io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + + (ACPI_PHYSICAL_ADDRESS) offset); - acpi_os_read_port (io_address, &value, width); + status = acpi_os_read_port (io_address, value, width); break; @@ -647,13 +730,20 @@ pci_id.bus = 0; pci_id.device = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address)); pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address)); - pci_register = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset); + pci_register = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + + offset); + + status = acpi_os_read_pci_configuration (&pci_id, pci_register, value, width); + break; + - acpi_os_read_pci_configuration (&pci_id, pci_register, &value, width); + default: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported address space: %X\n", reg->address_space_id)); + status = AE_BAD_PARAMETER; break; } - return value; + return (status); } @@ -673,7 +763,7 @@ * ******************************************************************************/ -void +acpi_status acpi_hw_low_level_write ( u32 width, u32 value, @@ -684,20 +774,21 @@ ACPI_IO_ADDRESS io_address; acpi_pci_id pci_id; u16 pci_register; + acpi_status status; - ACPI_FUNCTION_ENTRY (); + ACPI_FUNCTION_NAME ("Hw_low_level_write"); /* * Must have a valid pointer to a GAS structure, and - * a non-zero address within + * a non-zero address within. However, don't return an error + * because the PM1A/B code must not fail if B isn't present. */ if ((!reg) || (!ACPI_VALID_ADDRESS (reg->address))) { - return; + return (AE_OK); } - /* * Three address spaces supported: * Memory, Io, or PCI config. @@ -705,17 +796,19 @@ switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: - mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); + mem_address = (ACPI_GET_ADDRESS (reg->address) + + (ACPI_PHYSICAL_ADDRESS) offset); - acpi_os_write_memory (mem_address, value, width); + status = acpi_os_write_memory (mem_address, (acpi_integer) value, width); break; case ACPI_ADR_SPACE_SYSTEM_IO: - io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); + io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + + (ACPI_PHYSICAL_ADDRESS) offset); - acpi_os_write_port (io_address, value, width); + status = acpi_os_write_port (io_address, (acpi_integer) value, width); break; @@ -725,9 +818,18 @@ pci_id.bus = 0; pci_id.device = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address)); pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address)); - pci_register = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset); + pci_register = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + + offset); - acpi_os_write_pci_configuration (&pci_id, pci_register, value, width); + status = acpi_os_write_pci_configuration (&pci_id, pci_register, (acpi_integer) value, width); + break; + + + default: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported address space: %X\n", reg->address_space_id)); + status = AE_BAD_PARAMETER; break; } + + return (status); } diff -Nru a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c --- a/drivers/acpi/hardware/hwsleep.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/hardware/hwsleep.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface - * $Revision: 37 $ + * $Revision: 45 $ * *****************************************************************************/ @@ -25,8 +25,6 @@ */ #include "acpi.h" -#include "acnamesp.h" -#include "achware.h" #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME ("hwsleep") @@ -56,10 +54,12 @@ /* Set the vector */ if (acpi_gbl_common_fACS.vector_width == 32) { - *(u32 *) acpi_gbl_common_fACS.firmware_waking_vector = (u32) physical_address; + *(ACPI_CAST_PTR (u32, acpi_gbl_common_fACS.firmware_waking_vector)) + = (u32) physical_address; } else { - *acpi_gbl_common_fACS.firmware_waking_vector = physical_address; + *acpi_gbl_common_fACS.firmware_waking_vector + = physical_address; } return_ACPI_STATUS (AE_OK); @@ -95,10 +95,12 @@ /* Get the vector */ if (acpi_gbl_common_fACS.vector_width == 32) { - *physical_address = *(u32 *) acpi_gbl_common_fACS.firmware_waking_vector; + *physical_address = (ACPI_PHYSICAL_ADDRESS) + *(ACPI_CAST_PTR (u32, acpi_gbl_common_fACS.firmware_waking_vector)); } else { - *physical_address = *acpi_gbl_common_fACS.firmware_waking_vector; + *physical_address = + *acpi_gbl_common_fACS.firmware_waking_vector; } return_ACPI_STATUS (AE_OK); @@ -135,7 +137,7 @@ /* * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */ - status = acpi_hw_get_sleep_type_data (sleep_state, + status = acpi_get_sleep_type_data (sleep_state, &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); @@ -182,10 +184,12 @@ acpi_enter_sleep_state ( u8 sleep_state) { - u16 PM1Acontrol; - u16 PM1Bcontrol; + u32 PM1Acontrol; + u32 PM1Bcontrol; ACPI_BIT_REGISTER_INFO *sleep_type_reg_info; ACPI_BIT_REGISTER_INFO *sleep_enable_reg_info; + u32 in_value; + acpi_status status; ACPI_FUNCTION_TRACE ("Acpi_enter_sleep_state"); @@ -193,7 +197,7 @@ if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { - ACPI_REPORT_ERROR (("Sleep values out of range: A=%x B=%x\n", + ACPI_REPORT_ERROR (("Sleep values out of range: A=%X B=%X\n", acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); return_ACPI_STATUS (AE_AML_OPERAND_VALUE); } @@ -204,16 +208,34 @@ /* Clear wake status */ - acpi_hw_bit_register_write (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_LOCK); - acpi_hw_clear_acpi_status(); + status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - /* TBD: Disable arbitration here? */ + status = acpi_hw_clear_acpi_status(); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - acpi_hw_disable_non_wakeup_gpes(); + /* Disable BM arbitration */ + + status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_hw_disable_non_wakeup_gpes(); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* Get current value of PM1A control */ - PM1Acontrol = (u16) acpi_hw_register_read (ACPI_MTX_LOCK, ACPI_REGISTER_PM1_CONTROL); + status = acpi_hw_register_read (ACPI_MTX_LOCK, ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } ACPI_DEBUG_PRINT ((ACPI_DB_OK, "Entering S%d\n", sleep_state)); /* Clear SLP_EN and SLP_TYP fields */ @@ -228,8 +250,15 @@ /* Write #1: fill in SLP_TYP data */ - acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); - acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); + status = acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* Insert SLP_ENABLE bit */ @@ -237,26 +266,48 @@ PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask; /* Write #2: SLP_TYP + SLP_EN */ - ACPI_FLUSH_CPU_CACHE(); - acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); - acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); + ACPI_FLUSH_CPU_CACHE (); + + status = acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } /* * Wait a second, then try again. This is to get S4/5 to work on all machines. */ if (sleep_state > ACPI_STATE_S3) { - acpi_os_stall (1000000); - - acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1_CONTROL, - sleep_enable_reg_info->access_bit_mask); + /* + * We wait so long to allow chipsets that poll this reg very slowly to + * still read the right value. Ideally, this entire block would go + * away entirely. + */ + acpi_os_stall (10000000); + + status = acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1_CONTROL, + sleep_enable_reg_info->access_bit_mask); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } /* Wait until we enter sleep state */ - while (!acpi_hw_bit_register_read (ACPI_BITREG_WAKE_STATUS, ACPI_MTX_LOCK)) { + do { + status = acpi_get_register (ACPI_BITREG_WAKE_STATUS, &in_value, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + /* Spin until we wake */ - } + + } while (!in_value); return_ACPI_STATUS (AE_OK); } @@ -311,7 +362,13 @@ /* _WAK returns stuff - do we want to look at it? */ - acpi_hw_enable_non_wakeup_gpes(); + status = acpi_hw_enable_non_wakeup_gpes(); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - return_ACPI_STATUS (AE_OK); + /* Disable BM arbitration */ + status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK); + + return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c --- a/drivers/acpi/hardware/hwtimer.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/hardware/hwtimer.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Name: hwtimer.c - ACPI Power Management Timer Interface - * $Revision: 20 $ + * $Revision: 21 $ * *****************************************************************************/ @@ -25,7 +25,6 @@ */ #include "acpi.h" -#include "achware.h" #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME ("hwtimer") @@ -81,6 +80,9 @@ acpi_get_timer ( u32 *ticks) { + acpi_status status; + + ACPI_FUNCTION_TRACE ("Acpi_get_timer"); @@ -88,9 +90,9 @@ return_ACPI_STATUS (AE_BAD_PARAMETER); } - *ticks = acpi_hw_low_level_read (32, &acpi_gbl_FADT->Xpm_tmr_blk, 0); + status = acpi_hw_low_level_read (32, ticks, &acpi_gbl_FADT->Xpm_tmr_blk, 0); - return_ACPI_STATUS (AE_OK); + return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/include/acconfig.h b/drivers/acpi/include/acconfig.h --- a/drivers/acpi/include/acconfig.h Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/include/acconfig.h Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acconfig.h - Global configuration constants - * $Revision: 96 $ + * $Revision: 102 $ * *****************************************************************************/ @@ -54,7 +54,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20020403 +#define ACPI_CA_VERSION 0x20020517 /* Version of ACPI supported */ diff -Nru a/drivers/acpi/include/acdebug.h b/drivers/acpi/include/acdebug.h --- a/drivers/acpi/include/acdebug.h Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/include/acdebug.h Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acdebug.h - ACPI/AML debugger - * $Revision: 58 $ + * $Revision: 61 $ * *****************************************************************************/ @@ -63,7 +63,7 @@ * dbapi - external debugger interfaces */ -int +acpi_status acpi_db_initialize ( void); @@ -82,7 +82,6 @@ * dbcmds - debug commands and output routines */ - void acpi_db_display_table_info ( NATIVE_CHAR *table_arg); @@ -153,6 +152,38 @@ acpi_db_display_resources ( NATIVE_CHAR *object_arg); +void +acpi_db_check_integrity ( + void); + +acpi_status +acpi_db_integrity_walk ( + acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value); + +acpi_status +acpi_db_walk_and_match_name ( + acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value); + +acpi_status +acpi_db_walk_for_references ( + acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value); + +acpi_status +acpi_db_walk_for_specific_objects ( + acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value); + /* * dbdisasm - AML disassembler @@ -181,12 +212,20 @@ acpi_db_decode_internal_object ( acpi_operand_object *obj_desc); +u32 +acpi_db_block_type ( + acpi_parse_object *op); + +acpi_status +acpi_ps_display_object_pathname ( + acpi_walk_state *walk_state, + acpi_parse_object *op); + /* * dbdisply - debug display commands */ - void acpi_db_display_method_info ( acpi_parse_object *op); @@ -231,6 +270,14 @@ acpi_operand_object *obj_desc, acpi_walk_state *walk_state); +void +acpi_db_dump_parser_descriptor ( + acpi_parse_object *op); + +void * +acpi_db_get_pointer ( + void *target); + /* * dbexec - debugger control method execution @@ -248,6 +295,23 @@ NATIVE_CHAR *num_loops_arg, NATIVE_CHAR *method_name_arg); +acpi_status +acpi_db_execute_method ( + acpi_db_method_info *info, + acpi_buffer *return_obj); + +void +acpi_db_execute_setup ( + acpi_db_method_info *info); + +u32 +acpi_db_get_outstanding_allocations ( + void); + +void ACPI_SYSTEM_XFACE +acpi_db_method_thread ( + void *context); + /* * dbfileio - Debugger file I/O commands @@ -258,6 +322,9 @@ NATIVE_CHAR *user_argument, ARGUMENT_INFO *arguments); +acpi_status +ae_local_load_table ( + acpi_table_header *table_ptr); void acpi_db_close_debug_file ( @@ -310,6 +377,27 @@ NATIVE_CHAR prompt, acpi_parse_object *op); +void +acpi_db_display_help ( + NATIVE_CHAR *help_type); + +NATIVE_CHAR * +acpi_db_get_next_token ( + NATIVE_CHAR *string, + NATIVE_CHAR **next); + +u32 +acpi_db_get_line ( + NATIVE_CHAR *input_buffer); + +u32 +acpi_db_match_command ( + NATIVE_CHAR *user_command); + +void +acpi_db_single_thread ( + void); + /* * dbstats - Generation and display of ACPI table statistics @@ -324,6 +412,21 @@ acpi_status acpi_db_display_statistics ( NATIVE_CHAR *type_arg); + +acpi_status +acpi_db_classify_one_object ( + acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value); + +void +acpi_db_count_namespace_objects ( + void); + +void +acpi_db_enumerate_object ( + acpi_operand_object *obj_desc); /* diff -Nru a/drivers/acpi/include/acdispat.h b/drivers/acpi/include/acdispat.h --- a/drivers/acpi/include/acdispat.h Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/include/acdispat.h Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acdispat.h - dispatcher (parser to interpreter interface) - * $Revision: 52 $ + * $Revision: 54 $ * *****************************************************************************/ @@ -58,6 +58,13 @@ /* dsopcode - support for late evaluation */ acpi_status +acpi_ds_execute_arguments ( + acpi_namespace_node *node, + acpi_namespace_node *scope_node, + u32 aml_length, + u8 *aml_start); + +acpi_status acpi_ds_get_buffer_field_arguments ( acpi_operand_object *obj_desc); @@ -73,6 +80,35 @@ acpi_ds_get_package_arguments ( acpi_operand_object *obj_desc); +acpi_status +acpi_ds_init_buffer_field ( + u16 aml_opcode, + acpi_operand_object *obj_desc, + acpi_operand_object *buffer_desc, + acpi_operand_object *offset_desc, + acpi_operand_object *length_desc, + acpi_operand_object *result_desc); + +acpi_status +acpi_ds_eval_buffer_field_operands ( + acpi_walk_state *walk_state, + acpi_parse_object *op); + +acpi_status +acpi_ds_eval_region_operands ( + acpi_walk_state *walk_state, + acpi_parse_object *op); + +acpi_status +acpi_ds_eval_data_object_operands ( + acpi_walk_state *walk_state, + acpi_parse_object *op, + acpi_operand_object *obj_desc); + +acpi_status +acpi_ds_initialize_region ( + acpi_handle obj_handle); + /* dsctrl - Parser/Interpreter interface, control stack routines */ @@ -109,6 +145,12 @@ /* dsfield - Parser/Interpreter interface for AML fields */ acpi_status +acpi_ds_get_field_names ( + ACPI_CREATE_FIELD_INFO *info, + acpi_walk_state *walk_state, + acpi_parse_object *arg); + +acpi_status acpi_ds_create_field ( acpi_parse_object *op, acpi_namespace_node *region_node, @@ -180,7 +222,7 @@ acpi_walk_state *walk_state, acpi_operand_object ***node); -acpi_status +void acpi_ds_method_data_delete_all ( acpi_walk_state *walk_state); @@ -201,7 +243,7 @@ acpi_walk_state *walk_state, acpi_operand_object **dest_desc); -acpi_status +void acpi_ds_method_data_delete_value ( u16 opcode, u32 index, @@ -220,7 +262,7 @@ acpi_walk_state *walk_state, acpi_namespace_node **node); -acpi_status +void acpi_ds_method_data_init ( acpi_walk_state *walk_state); @@ -306,29 +348,6 @@ acpi_walk_state *walk_state, acpi_namespace_node *node, acpi_parse_object *op); - - -/* dsregn - Parser/Interpreter interface - Op Region parsing */ - -acpi_status -acpi_ds_eval_buffer_field_operands ( - acpi_walk_state *walk_state, - acpi_parse_object *op); - -acpi_status -acpi_ds_eval_region_operands ( - acpi_walk_state *walk_state, - acpi_parse_object *op); - -acpi_status -acpi_ds_eval_data_object_operands ( - acpi_walk_state *walk_state, - acpi_parse_object *op, - acpi_operand_object *obj_desc); - -acpi_status -acpi_ds_initialize_region ( - acpi_handle obj_handle); /* dsutils - Parser/Interpreter interface utility routines */ diff -Nru a/drivers/acpi/include/acevents.h b/drivers/acpi/include/acevents.h --- a/drivers/acpi/include/acevents.h Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/include/acevents.h Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acevents.h - Event subcomponent prototypes and defines - * $Revision: 76 $ + * $Revision: 79 $ * *****************************************************************************/ @@ -65,7 +65,7 @@ acpi_ev_acquire_global_lock( u32 timeout); -void +acpi_status acpi_ev_release_global_lock( void); @@ -116,7 +116,7 @@ */ acpi_status -acpi_ev_install_default_address_space_handlers ( +acpi_ev_init_address_spaces ( void); acpi_status @@ -125,7 +125,7 @@ u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, - acpi_integer *value); + void *value); acpi_status acpi_ev_addr_handler_helper ( @@ -134,15 +134,15 @@ void *context, void **return_value); -void -acpi_ev_disassociate_region_from_handler( - acpi_operand_object *region_obj, - u8 acpi_ns_is_locked); - acpi_status -acpi_ev_associate_region_and_handler ( +acpi_ev_attach_region ( acpi_operand_object *handler_obj, acpi_operand_object *region_obj, + u8 acpi_ns_is_locked); + +void +acpi_ev_detach_region ( + acpi_operand_object *region_obj, u8 acpi_ns_is_locked); diff -Nru a/drivers/acpi/include/acexcep.h b/drivers/acpi/include/acexcep.h --- a/drivers/acpi/include/acexcep.h Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/include/acexcep.h Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acexcep.h - Exception codes returned by the ACPI subsystem - * $Revision: 59 $ + * $Revision: 63 $ * *****************************************************************************/ @@ -102,8 +102,9 @@ #define AE_BAD_CHECKSUM (acpi_status) (0x0003 | AE_CODE_ACPI_TABLES) #define AE_BAD_VALUE (acpi_status) (0x0004 | AE_CODE_ACPI_TABLES) #define AE_TABLE_NOT_SUPPORTED (acpi_status) (0x0005 | AE_CODE_ACPI_TABLES) +#define AE_INVALID_TABLE_LENGTH (acpi_status) (0x0006 | AE_CODE_ACPI_TABLES) -#define AE_CODE_TBL_MAX 0x0005 +#define AE_CODE_TBL_MAX 0x0006 /* @@ -138,8 +139,11 @@ #define AE_AML_INVALID_INDEX (acpi_status) (0x001A | AE_CODE_AML) #define AE_AML_REGISTER_LIMIT (acpi_status) (0x001B | AE_CODE_AML) #define AE_AML_NO_WHILE (acpi_status) (0x001C | AE_CODE_AML) +#define AE_AML_ALIGNMENT (acpi_status) (0x001D | AE_CODE_AML) +#define AE_AML_NO_RESOURCE_END_TAG (acpi_status) (0x001E | AE_CODE_AML) +#define AE_AML_BAD_RESOURCE_VALUE (acpi_status) (0x001F | AE_CODE_AML) -#define AE_CODE_AML_MAX 0x001C +#define AE_CODE_AML_MAX 0x001F /* * Internal exceptions used for control @@ -215,7 +219,8 @@ "AE_BAD_HEADER", "AE_BAD_CHECKSUM", "AE_BAD_VALUE", - "AE_TABLE_NOT_SUPPORTED" + "AE_TABLE_NOT_SUPPORTED", + "AE_INVALID_TABLE_LENGTH" }; NATIVE_CHAR const *acpi_gbl_exception_names_aml[] = @@ -247,7 +252,10 @@ "AE_AML_INVALID_RESOURCE_TYPE", "AE_AML_INVALID_INDEX", "AE_AML_REGISTER_LIMIT", - "AE_AML_NO_WHILE" + "AE_AML_NO_WHILE", + "AE_AML_ALIGNMENT", + "AE_AML_NO_RESOURCE_END_TAG", + "AE_AML_BAD_RESOURCE_VALUE" }; NATIVE_CHAR const *acpi_gbl_exception_names_ctrl[] = diff -Nru a/drivers/acpi/include/acglobal.h b/drivers/acpi/include/acglobal.h --- a/drivers/acpi/include/acglobal.h Sun Jun 2 18:44:55 2002 +++ b/drivers/acpi/include/acglobal.h Sun Jun 2 18:44:55 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acglobal.h - Declarations for global variables - * $Revision: 121 $ + * $Revision: 125 $ * *****************************************************************************/ @@ -80,6 +80,14 @@ ACPI_EXTERN acpi_common_facs acpi_gbl_common_fACS; /* + * Handle both ACPI 1.0 and ACPI 2.0 Integer widths + * If we are running a method that exists in a 32-bit ACPI table. + * Use only 32 bits of the Integer for conversion. + */ +ACPI_EXTERN u8 acpi_gbl_integer_bit_width; +ACPI_EXTERN u8 acpi_gbl_integer_byte_width; + +/* * Since there may be multiple SSDTs and PSDTS, a single pointer is not * sufficient; Therefore, there isn't one! */ @@ -109,6 +117,7 @@ ACPI_EXTERN ACPI_MEMORY_LIST acpi_gbl_memory_lists[ACPI_NUM_MEM_LISTS]; ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER acpi_gbl_drv_notify; ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER acpi_gbl_sys_notify; +ACPI_EXTERN ACPI_INIT_HANDLER acpi_gbl_init_handler; ACPI_EXTERN acpi_walk_state *acpi_gbl_breakpoint_walk; ACPI_EXTERN acpi_handle acpi_gbl_global_lock_semaphore; @@ -131,6 +140,7 @@ extern u32 acpi_gbl_startup_flags; extern const u8 acpi_gbl_decode_to8bit[8]; extern const NATIVE_CHAR *acpi_gbl_db_sleep_states[ACPI_NUM_SLEEP_STATES]; +extern const acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; /***************************************************************************** @@ -186,7 +196,7 @@ * ****************************************************************************/ -ACPI_EXTERN ACPI_BIT_REGISTER_INFO acpi_gbl_bit_register_info[ACPI_NUM_BITREG]; +extern ACPI_BIT_REGISTER_INFO acpi_gbl_bit_register_info[ACPI_NUM_BITREG]; ACPI_EXTERN u8 acpi_gbl_sleep_type_a; ACPI_EXTERN u8 acpi_gbl_sleep_type_b; @@ -229,13 +239,11 @@ #ifdef ENABLE_DEBUGGER -ACPI_EXTERN u8 acpi_gbl_method_executing; -ACPI_EXTERN u8 acpi_gbl_db_terminate_threads; +extern u8 acpi_gbl_method_executing; +extern u8 acpi_gbl_db_terminate_threads; ACPI_EXTERN int optind; ACPI_EXTERN NATIVE_CHAR *optarg; -ACPI_EXTERN u8 *aml_start; -ACPI_EXTERN u32 aml_length; ACPI_EXTERN u8 acpi_gbl_db_opt_tables; ACPI_EXTERN u8 acpi_gbl_db_opt_disasm; diff -Nru a/drivers/acpi/include/achware.h b/drivers/acpi/include/achware.h --- a/drivers/acpi/include/achware.h Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/include/achware.h Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: achware.h -- hardware specific interfaces - * $Revision: 58 $ + * $Revision: 60 $ * *****************************************************************************/ @@ -64,49 +64,44 @@ acpi_hw_get_bit_register_info ( u32 register_id); -u32 -acpi_hw_bit_register_read ( - u32 register_id, - u32 flags); - -u32 -acpi_hw_bit_register_write ( - u32 register_id, - u32 value, - u32 flags); - -u32 +acpi_status acpi_hw_register_read ( u8 use_lock, - u32 register_id); + u32 register_id, + u32 *return_value); -void +acpi_status acpi_hw_register_write ( u8 use_lock, u32 register_id, u32 value); -u32 +acpi_status acpi_hw_low_level_read ( u32 width, + u32 *value, acpi_generic_address *reg, u32 offset); -void +acpi_status acpi_hw_low_level_write ( u32 width, u32 value, acpi_generic_address *reg, u32 offset); -void +acpi_status acpi_hw_clear_acpi_status ( void); /* GPE support */ -void +u8 +acpi_hw_get_gpe_bit_mask ( + u32 gpe_number); + +acpi_status acpi_hw_enable_gpe ( u32 gpe_number); @@ -114,7 +109,7 @@ acpi_hw_enable_gpe_for_wakeup ( u32 gpe_number); -void +acpi_status acpi_hw_disable_gpe ( u32 gpe_number); @@ -122,31 +117,22 @@ acpi_hw_disable_gpe_for_wakeup ( u32 gpe_number); -void +acpi_status acpi_hw_clear_gpe ( u32 gpe_number); -void +acpi_status acpi_hw_get_gpe_status ( u32 gpe_number, acpi_event_status *event_status); -void +acpi_status acpi_hw_disable_non_wakeup_gpes ( void); -void +acpi_status acpi_hw_enable_non_wakeup_gpes ( void); - - -/* Sleep Prototypes */ - -acpi_status -acpi_hw_get_sleep_type_data ( - u8 sleep_state, - u8 *slp_typ_a, - u8 *slp_typ_b); /* ACPI Timer prototypes */ diff -Nru a/drivers/acpi/include/acinterp.h b/drivers/acpi/include/acinterp.h --- a/drivers/acpi/include/acinterp.h Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/include/acinterp.h Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acinterp.h - Interpreter subcomponent prototypes and defines - * $Revision: 133 $ + * $Revision: 137 $ * *****************************************************************************/ @@ -36,6 +36,11 @@ acpi_operand_object **stack_ptr, acpi_walk_state *walk_state); +acpi_status +acpi_ex_check_object_type ( + acpi_object_type type_needed, + acpi_object_type this_type, + void *object); /* * exxface - External interpreter interfaces @@ -83,6 +88,11 @@ acpi_operand_object **result_desc, acpi_walk_state *walk_state); +u32 +acpi_ex_convert_to_ascii ( + acpi_integer integer, + u32 base, + u8 *string); /* * exfield - ACPI AML (p-code) execution - field manipulation @@ -172,6 +182,12 @@ acpi_ex_opcode_6A_0T_1R ( acpi_walk_state *walk_state); +u8 +acpi_ex_do_match ( + u32 match_op, + acpi_integer package_value, + acpi_integer match_value); + acpi_status acpi_ex_get_object_reference ( acpi_operand_object *obj_desc, @@ -283,7 +299,7 @@ acpi_operand_object *obj_desc, acpi_walk_state *walk_state); -acpi_status +void acpi_ex_release_all_mutexes ( ACPI_THREAD_STATE *thread); @@ -423,13 +439,6 @@ */ void -acpi_ex_show_hex_value ( - u32 byte_count, - u8 *aml_start, - u32 lead_space); - - -acpi_status acpi_ex_dump_operand ( acpi_operand_object *entry_desc); @@ -448,12 +457,31 @@ acpi_operand_object *object, u32 flags); - void acpi_ex_dump_node ( acpi_namespace_node *node, u32 flags); +void +acpi_ex_out_string ( + char *title, + char *value); + +void +acpi_ex_out_pointer ( + char *title, + void *value); + +void +acpi_ex_out_integer ( + char *title, + u32 value); + +void +acpi_ex_out_address ( + char *title, + ACPI_PHYSICAL_ADDRESS value); + /* * exnames - interpreter/scanner name load/execute @@ -586,7 +614,7 @@ acpi_ex_acquire_global_lock ( u32 rule); -acpi_status +void acpi_ex_release_global_lock ( u8 locked); @@ -595,12 +623,12 @@ acpi_integer value, u32 base); -acpi_status +void acpi_ex_eisa_id_to_string ( u32 numeric_id, NATIVE_CHAR *out_string); -acpi_status +void acpi_ex_unsigned_integer_to_string ( acpi_integer value, NATIVE_CHAR *out_string); diff -Nru a/drivers/acpi/include/aclocal.h b/drivers/acpi/include/aclocal.h --- a/drivers/acpi/include/aclocal.h Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/include/aclocal.h Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: aclocal.h - Internal data types used across the ACPI subsystem - * $Revision: 162 $ + * $Revision: 167 $ * *****************************************************************************/ @@ -37,23 +37,9 @@ #define ACPI_LOGICAL_ADDRESSING 0x00 #define ACPI_PHYSICAL_ADDRESSING 0x01 -/* Object descriptor types */ +/* Total number of aml opcodes defined */ -#define ACPI_CACHED_OBJECT 0x11 /* ORed in when object is cached */ -#define ACPI_DESC_TYPE_STATE 0x20 -#define ACPI_DESC_TYPE_STATE_UPDATE 0x21 -#define ACPI_DESC_TYPE_STATE_PACKAGE 0x22 -#define ACPI_DESC_TYPE_STATE_CONTROL 0x23 -#define ACPI_DESC_TYPE_STATE_RPSCOPE 0x24 -#define ACPI_DESC_TYPE_STATE_PSCOPE 0x25 -#define ACPI_DESC_TYPE_STATE_WSCOPE 0x26 -#define ACPI_DESC_TYPE_STATE_RESULT 0x27 -#define ACPI_DESC_TYPE_STATE_NOTIFY 0x28 -#define ACPI_DESC_TYPE_STATE_THREAD 0x29 -#define ACPI_DESC_TYPE_WALK 0x44 -#define ACPI_DESC_TYPE_PARSER 0x66 -#define ACPI_DESC_TYPE_INTERNAL 0x88 -#define ACPI_DESC_TYPE_NAMED 0xAA +#define AML_NUM_OPCODES 0x7E /***************************************************************************** @@ -234,7 +220,7 @@ u8 *aml_start; u64 physical_address; u32 aml_length; - u32 length; + ACPI_SIZE length; u32 count; acpi_owner_id table_id; u8 type; @@ -411,8 +397,8 @@ /* Forward declarations */ struct acpi_walk_state; -struct acpi_parse_obj; struct acpi_obj_mutex; +union acpi_parse_obj; #define ACPI_STATE_COMMON /* Two 32-bit fields and a pointer */\ @@ -463,7 +449,7 @@ typedef struct acpi_control_state { ACPI_STATE_COMMON - struct acpi_parse_obj *predicate_op; + union acpi_parse_obj *predicate_op; u8 *aml_predicate_start; /* Start of if/while predicate */ u8 *package_end; /* End of if/while block */ u16 opcode; @@ -485,7 +471,7 @@ typedef struct acpi_pscope_state { ACPI_STATE_COMMON - struct acpi_parse_obj *op; /* current op being parsed */ + union acpi_parse_obj *op; /* current op being parsed */ u8 *arg_end; /* current argument end */ u8 *pkg_end; /* current package end */ u32 arg_list; /* next argument to parse */ @@ -526,7 +512,7 @@ typedef acpi_status (*acpi_parse_downwards) ( struct acpi_walk_state *walk_state, - struct acpi_parse_obj **out_op); + union acpi_parse_obj **out_op); typedef acpi_status (*acpi_parse_upwards) ( @@ -609,7 +595,7 @@ NATIVE_CHAR *string; /* NULL terminated string */ u8 *buffer; /* buffer or string */ NATIVE_CHAR *name; /* NULL terminated string */ - struct acpi_parse_obj *arg; /* arguments and contained ops */ + union acpi_parse_obj *arg; /* arguments and contained ops */ } acpi_parse_value; @@ -617,12 +603,12 @@ #define ACPI_PARSE_COMMON \ u8 data_type; /* To differentiate various internal objs */\ u8 flags; /* Type of Op */\ - u16 opcode; /* AML opcode */\ + u16 aml_opcode; /* AML opcode */\ u32 aml_offset; /* offset of declaration in AML */\ - struct acpi_parse_obj *parent; /* parent op */\ - struct acpi_parse_obj *next; /* next op */\ + union acpi_parse_obj *parent; /* parent op */\ + union acpi_parse_obj *next; /* next op */\ ACPI_DEBUG_ONLY_MEMBERS (\ - NATIVE_CHAR op_name[16]) /* op name (debug only) */\ + NATIVE_CHAR aml_op_name[16]) /* op name (debug only) */\ /* NON-DEBUG members below: */\ acpi_namespace_node *node; /* for use by interpreter */\ acpi_parse_value value; /* Value or args associated with the opcode */\ @@ -631,24 +617,68 @@ /* * generic operation (eg. If, While, Store) */ -typedef struct acpi_parse_obj +typedef struct acpi_parseobj_common { ACPI_PARSE_COMMON -} acpi_parse_object; +} ACPI_PARSE_OBJ_COMMON; /* * Extended Op for named ops (Scope, Method, etc.), deferred ops (Methods and Op_regions), * and bytelists. */ -typedef struct acpi_parse2_obj +typedef struct acpi_parseobj_named { ACPI_PARSE_COMMON u8 *data; /* AML body or bytelist data */ u32 length; /* AML length */ u32 name; /* 4-byte name or zero if no name */ -} acpi_parse2_object; +} ACPI_PARSE_OBJ_NAMED; + + +/* The parse node is the fundamental element of the parse tree */ + +typedef struct acpi_parseobj_asl +{ + ACPI_PARSE_COMMON + + union acpi_parse_obj *child; + + + union acpi_parse_obj *parent_method; + char *filename; + char *external_name; + char *namepath; + u32 extra_value; + u32 column; + u32 line_number; + u32 logical_line_number; + u32 logical_byte_offset; + u32 end_line; + u32 end_logical_line; + u16 parse_opcode; + u32 acpi_btype; + u32 aml_length; + u32 aml_subtree_length; + u32 final_aml_length; + u32 final_aml_offset; + u8 aml_opcode_length; + u8 aml_pkg_len_bytes; + u16 compile_flags; + u8 extra; + char parse_op_name[12]; + +} ACPI_PARSE_OBJ_ASL; + + +typedef union acpi_parse_obj +{ + ACPI_PARSE_OBJ_COMMON common; + ACPI_PARSE_OBJ_NAMED named; + ACPI_PARSE_OBJ_ASL asl; + +} acpi_parse_object; /* @@ -663,10 +693,10 @@ u8 *aml_end; /* (last + 1) AML byte */ u8 *pkg_start; /* current package begin */ u8 *pkg_end; /* current package end */ - struct acpi_parse_obj *start_op; /* root of parse tree */ + union acpi_parse_obj *start_op; /* root of parse tree */ struct acpi_node *start_node; union acpi_gen_state *scope; /* current scope */ - struct acpi_parse_obj *start_scope; + union acpi_parse_obj *start_scope; } acpi_parse_state; @@ -712,38 +742,6 @@ #define ACPI_REGISTER_SMI_COMMAND_BLOCK 0x09 -/* - * Bit_register IDs - * These are bitfields defined within the full ACPI registers - */ -#define ACPI_BITREG_TIMER_STATUS 0x00 -#define ACPI_BITREG_BUS_MASTER_STATUS 0x01 -#define ACPI_BITREG_GLOBAL_LOCK_STATUS 0x02 -#define ACPI_BITREG_POWER_BUTTON_STATUS 0x03 -#define ACPI_BITREG_SLEEP_BUTTON_STATUS 0x04 -#define ACPI_BITREG_RT_CLOCK_STATUS 0x05 -#define ACPI_BITREG_WAKE_STATUS 0x06 - -#define ACPI_BITREG_TIMER_ENABLE 0x07 -#define ACPI_BITREG_GLOBAL_LOCK_ENABLE 0x08 -#define ACPI_BITREG_POWER_BUTTON_ENABLE 0x09 -#define ACPI_BITREG_SLEEP_BUTTON_ENABLE 0x0A -#define ACPI_BITREG_RT_CLOCK_ENABLE 0x0B -#define ACPI_BITREG_WAKE_ENABLE 0x0C - -#define ACPI_BITREG_SCI_ENABLE 0x0D -#define ACPI_BITREG_BUS_MASTER_RLD 0x0E -#define ACPI_BITREG_GLOBAL_LOCK_RELEASE 0x0F -#define ACPI_BITREG_SLEEP_TYPE_A 0x10 -#define ACPI_BITREG_SLEEP_TYPE_B 0x11 -#define ACPI_BITREG_SLEEP_ENABLE 0x12 - -#define ACPI_BITREG_ARB_DISABLE 0x13 - -#define ACPI_BITREG_MAX 0x13 -#define ACPI_NUM_BITREG ACPI_BITREG_MAX + 1 - - /* Masks used to access the Bit_registers */ #define ACPI_BITMASK_TIMER_STATUS 0x0001 @@ -870,6 +868,7 @@ ****************************************************************************/ #define ACPI_ASCII_ZERO 0x30 + /***************************************************************************** * diff -Nru a/drivers/acpi/include/acmacros.h b/drivers/acpi/include/acmacros.h --- a/drivers/acpi/include/acmacros.h Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/include/acmacros.h Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acmacros.h - C macros for the entire subsystem. - * $Revision: 115 $ + * $Revision: 123 $ * *****************************************************************************/ @@ -31,22 +31,23 @@ * Data manipulation macros */ -#define ACPI_LOWORD(l) ((u16)(NATIVE_UINT)(l)) -#define ACPI_HIWORD(l) ((u16)((((NATIVE_UINT)(l)) >> 16) & 0xFFFF)) +#define ACPI_LOWORD(l) ((u16)(u32)(l)) +#define ACPI_HIWORD(l) ((u16)((((u32)(l)) >> 16) & 0xFFFF)) #define ACPI_LOBYTE(l) ((u8)(u16)(l)) #define ACPI_HIBYTE(l) ((u8)((((u16)(l)) >> 8) & 0xFF)) -#ifdef _IA16 +#if ACPI_MACHINE_WIDTH == 16 + /* * For 16-bit addresses, we have to assume that the upper 32 bits * are zero. */ -#define ACPI_LODWORD(l) (l) -#define ACPI_HIDWORD(l) (0) +#define ACPI_LODWORD(l) ((u32)(l)) +#define ACPI_HIDWORD(l) ((u32)(0)) #define ACPI_GET_ADDRESS(a) ((a).lo) -#define ACPI_STORE_ADDRESS(a,b) {(a).hi=0;(a).lo=(b);} +#define ACPI_STORE_ADDRESS(a,b) {(a).hi=0;(a).lo=(u32)(b);} #define ACPI_VALID_ADDRESS(a) ((a).hi | (a).lo) #else @@ -55,7 +56,7 @@ * acpi_integer is 32-bits, no 64-bit support on this platform */ #define ACPI_LODWORD(l) ((u32)(l)) -#define ACPI_HIDWORD(l) (0) +#define ACPI_HIDWORD(l) ((u32)(0)) #define ACPI_GET_ADDRESS(a) (a) #define ACPI_STORE_ADDRESS(a,b) ((a)=(b)) @@ -67,10 +68,10 @@ * Full 64-bit address/integer on both 32-bit and 64-bit platforms */ #define ACPI_LODWORD(l) ((u32)(u64)(l)) -#define ACPI_HIDWORD(l) ((u32)(((*(uint64_struct *)(&l))).hi)) +#define ACPI_HIDWORD(l) ((u32)(((*(uint64_struct *)(void *)(&l))).hi)) #define ACPI_GET_ADDRESS(a) (a) -#define ACPI_STORE_ADDRESS(a,b) ((a)=(b)) +#define ACPI_STORE_ADDRESS(a,b) ((a)=(ACPI_PHYSICAL_ADDRESS)(b)) #define ACPI_VALID_ADDRESS(a) (a) #endif #endif @@ -83,20 +84,23 @@ /* Pointer arithmetic */ -#define ACPI_PTR_ADD(t,a,b) (t *) ((char *)(a) + (b)) +#define ACPI_PTR_ADD(t,a,b) (t *) (void *)((char *)(a) + (NATIVE_UINT)(b)) #define ACPI_PTR_DIFF(a,b) (NATIVE_UINT) ((char *)(a) - (char *)(b)) /* Pointer/Integer type conversions */ -#define ACPI_TO_POINTER(i) ACPI_PTR_ADD (void,NULL,(NATIVE_UINT)i) -#define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p,NULL) -#define ACPI_OFFSET(d,o) ((ACPI_SIZE) ACPI_TO_INTEGER (&(((d *)0)->o))) -#define ACPI_FADT_OFFSET(o) ACPI_OFFSET (FADT_DESCRIPTOR, o) +#define ACPI_TO_POINTER(i) ACPI_PTR_ADD (void, (void *) NULL,(NATIVE_UINT)i) +#define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p,(void *) NULL) +#define ACPI_OFFSET(d,f) (ACPI_SIZE) ACPI_PTR_DIFF (&(((d *)0)->f),(void *) NULL) +#define ACPI_FADT_OFFSET(f) ACPI_OFFSET (FADT_DESCRIPTOR, f) +#define ACPI_CAST_PTR(t, p) ((t *)(void *)(p)) +#define ACPI_CAST_INDIRECT_PTR(t, p) ((t **)(void *)(p)) -#ifdef _IA16 +#if ACPI_MACHINE_WIDTH == 16 +#define ACPI_STORE_POINTER(d,s) ACPI_MOVE_UNALIGNED32_TO_32(d,s) #define ACPI_PHYSADDR_TO_PTR(i) (void *)(i) -#define ACPI_PTR_TO_PHYSADDR(i) (char *)(i) +#define ACPI_PTR_TO_PHYSADDR(i) (u32) (char *)(i) #else #define ACPI_PHYSADDR_TO_PTR(i) ACPI_TO_POINTER(i) #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) @@ -112,10 +116,10 @@ /* The hardware supports unaligned transfers, just do the move */ -#define ACPI_MOVE_UNALIGNED16_TO_16(d,s) *(u16 *)(d) = *(u16 *)(s) -#define ACPI_MOVE_UNALIGNED32_TO_32(d,s) *(u32 *)(d) = *(u32 *)(s) -#define ACPI_MOVE_UNALIGNED16_TO_32(d,s) *(u32 *)(d) = *(u16 *)(s) -#define ACPI_MOVE_UNALIGNED64_TO_64(d,s) *(u64 *)(d) = *(u64 *)(s) +#define ACPI_MOVE_UNALIGNED16_TO_16(d,s) *(u16 *)(void *)(d) = *(u16 *)(void *)(s) +#define ACPI_MOVE_UNALIGNED32_TO_32(d,s) *(u32 *)(void *)(d) = *(u32 *)(void *)(s) +#define ACPI_MOVE_UNALIGNED16_TO_32(d,s) *(u32 *)(void *)(d) = *(u16 *)(void *)(s) +#define ACPI_MOVE_UNALIGNED64_TO_64(d,s) *(u64 *)(void *)(d) = *(u64 *)(void *)(s) #else /* @@ -124,24 +128,24 @@ * the destination (or both) is/are unaligned. */ -#define ACPI_MOVE_UNALIGNED16_TO_16(d,s) {((u8 *)(d))[0] = ((u8 *)(s))[0];\ - ((u8 *)(d))[1] = ((u8 *)(s))[1];} +#define ACPI_MOVE_UNALIGNED16_TO_16(d,s) {((u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\ + ((u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[1];} -#define ACPI_MOVE_UNALIGNED32_TO_32(d,s) {((u8 *)(d))[0] = ((u8 *)(s))[0];\ - ((u8 *)(d))[1] = ((u8 *)(s))[1];\ - ((u8 *)(d))[2] = ((u8 *)(s))[2];\ - ((u8 *)(d))[3] = ((u8 *)(s))[3];} - -#define ACPI_MOVE_UNALIGNED16_TO_32(d,s) {(*(u32*)(d)) = 0; ACPI_MOVE_UNALIGNED16_TO_16(d,s);} - -#define ACPI_MOVE_UNALIGNED64_TO_64(d,s) {((u8 *)(d))[0] = ((u8 *)(s))[0];\ - ((u8 *)(d))[1] = ((u8 *)(s))[1];\ - ((u8 *)(d))[2] = ((u8 *)(s))[2];\ - ((u8 *)(d))[3] = ((u8 *)(s))[3];\ - ((u8 *)(d))[4] = ((u8 *)(s))[4];\ - ((u8 *)(d))[5] = ((u8 *)(s))[5];\ - ((u8 *)(d))[6] = ((u8 *)(s))[6];\ - ((u8 *)(d))[7] = ((u8 *)(s))[7];} +#define ACPI_MOVE_UNALIGNED32_TO_32(d,s) {((u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\ + ((u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[1];\ + ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[2];\ + ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[3];} + +#define ACPI_MOVE_UNALIGNED16_TO_32(d,s) {(*(u32*)(void *)(d)) = 0; ACPI_MOVE_UNALIGNED16_TO_16(d,s);} + +#define ACPI_MOVE_UNALIGNED64_TO_64(d,s) {((u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0];\ + ((u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[1];\ + ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[2];\ + ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[3];\ + ((u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[4];\ + ((u8 *)(void *)(d))[5] = ((u8 *)(void *)(s))[5];\ + ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[6];\ + ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[7];} #endif @@ -174,8 +178,8 @@ /* * Rounding macros (Power of two boundaries only) */ -#define ACPI_ROUND_DOWN(value,boundary) (((NATIVE_UINT)(value)) & (~((boundary)-1))) -#define ACPI_ROUND_UP(value,boundary) ((((NATIVE_UINT)(value)) + ((boundary)-1)) & (~((boundary)-1))) +#define ACPI_ROUND_DOWN(value,boundary) (((NATIVE_UINT)(value)) & (~(((NATIVE_UINT) boundary)-1))) +#define ACPI_ROUND_UP(value,boundary) ((((NATIVE_UINT)(value)) + (((NATIVE_UINT) boundary)-1)) & (~(((NATIVE_UINT) boundary)-1))) #define ACPI_ROUND_DOWN_TO_32_BITS(a) ACPI_ROUND_DOWN(a,4) #define ACPI_ROUND_DOWN_TO_64_BITS(a) ACPI_ROUND_DOWN(a,8) @@ -201,22 +205,33 @@ * MASK_BITS_ABOVE creates a mask starting AT the position and above * MASK_BITS_BELOW creates a mask starting one bit BELOW the position */ -#define ACPI_MASK_BITS_ABOVE(position) (~(((acpi_integer)(-1)) << ((u32) (position)))) -#define ACPI_MASK_BITS_BELOW(position) (((acpi_integer)(-1)) << ((u32) (position))) +#define ACPI_MASK_BITS_ABOVE(position) (~((ACPI_INTEGER_MAX) << ((u32) (position)))) +#define ACPI_MASK_BITS_BELOW(position) ((ACPI_INTEGER_MAX) << ((u32) (position))) #define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7')) /* Macros for GAS addressing */ -#ifndef _IA16 +#if ACPI_MACHINE_WIDTH != 16 #define ACPI_PCI_DEVICE_MASK (u64) 0x0000FFFF00000000 #define ACPI_PCI_FUNCTION_MASK (u64) 0x00000000FFFF0000 #define ACPI_PCI_REGISTER_MASK (u64) 0x000000000000FFFF -#define ACPI_PCI_FUNCTION(a) (u16) ((((a) & ACPI_PCI_FUNCTION_MASK) >> 16)) -#define ACPI_PCI_DEVICE(a) (u16) ((((a) & ACPI_PCI_DEVICE_MASK) >> 32)) -#define ACPI_PCI_REGISTER(a) (u16) (((a) & ACPI_PCI_REGISTER_MASK)) +/* + * Obsolete + */ + +/* +#define ACPI_PCI_FUNCTION(a) (u16) ((((u64)((u64)(a) & ACPI_PCI_FUNCTION_MASK)) >> 16)) +#define ACPI_PCI_DEVICE(a) (u16) ((((u64)((u64)(a) & ACPI_PCI_DEVICE_MASK)) >> 32)) +#define ACPI_PCI_REGISTER(a) (u16) (((u64)((u64)(a) & ACPI_PCI_REGISTER_MASK))) +*/ + + +#define ACPI_PCI_DEVICE(a) (u16) ((ACPI_HIDWORD ((a))) & 0x0000FFFF) +#define ACPI_PCI_FUNCTION(a) (u16) ((ACPI_LODWORD ((a))) >> 16) +#define ACPI_PCI_REGISTER(a) (u16) ((ACPI_LODWORD ((a))) & 0x0000FFFF) #else @@ -241,13 +256,13 @@ * * The "Descriptor" field is the first field in both structures. */ -#define ACPI_GET_DESCRIPTOR_TYPE(d) (((acpi_namespace_node *)d)->descriptor) -#define ACPI_SET_DESCRIPTOR_TYPE(d,t) (((acpi_namespace_node *)d)->descriptor = t) +#define ACPI_GET_DESCRIPTOR_TYPE(d) (((ACPI_DESCRIPTOR *)(void *)(d))->descriptor_id) +#define ACPI_SET_DESCRIPTOR_TYPE(d,t) (((ACPI_DESCRIPTOR *)(void *)(d))->descriptor_id = t) /* Macro to test the object type */ -#define ACPI_GET_OBJECT_TYPE(d) (((acpi_operand_object *)d)->common.type) +#define ACPI_GET_OBJECT_TYPE(d) (((acpi_operand_object *)(void *)d)->common.type) /* Macro to check the table flags for SINGLE or MULTIPLE tables are allowed */ @@ -259,7 +274,7 @@ * as a pointer to an acpi_table_header. (b+1) then points past the header, * and ((u8 *)b+b->Length) points one byte past the end of the table. */ -#ifndef _IA16 +#if ACPI_MACHINE_WIDTH != 16 #define ACPI_IS_IN_ACPI_TABLE(a,b) (((u8 *)(a) >= (u8 *)(b + 1)) &&\ ((u8 *)(a) < ((u8 *)b + b->length))) @@ -272,7 +287,7 @@ /* * Macros for the master AML opcode table */ -#ifdef ACPI_DEBUG +#if defined(ACPI_DEBUG) || defined(ENABLE_DEBUGGER) #define ACPI_OP(name,Pargs,Iargs,obj_type,class,type,flags) {name,Pargs,Iargs,flags,obj_type,class,type} #else #define ACPI_OP(name,Pargs,Iargs,obj_type,class,type,flags) {Pargs,Iargs,flags,obj_type,class,type} @@ -317,7 +332,7 @@ a.register_bit_width = (u8) ACPI_MUL_8 (b);\ a.register_bit_offset = 0;\ a.reserved = 0;\ - ACPI_STORE_ADDRESS (a.address,c);} + ACPI_STORE_ADDRESS (a.address,(ACPI_PHYSICAL_ADDRESS) c);} /* ACPI V1.0 entries -- address space is always I/O */ @@ -402,11 +417,16 @@ * One of the FUNCTION_TRACE macros above must be used in conjunction with these macros * so that "_Proc_name" is defined. */ -#define return_VOID {acpi_ut_exit(__LINE__,&_dbg);return;} -#define return_ACPI_STATUS(s) {acpi_ut_status_exit(__LINE__,&_dbg,s);return(s);} -#define return_VALUE(s) {acpi_ut_value_exit(__LINE__,&_dbg,s);return(s);} -#define return_PTR(s) {acpi_ut_ptr_exit(__LINE__,&_dbg,(u8 *)s);return(s);} +#ifdef ACPI_USE_DO_WHILE_0 +#define ACPI_DO_WHILE0(a) do a while(0) +#else +#define ACPI_DO_WHILE0(a) a +#endif +#define return_VOID ACPI_DO_WHILE0 ({acpi_ut_exit(__LINE__,&_dbg);return;}) +#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({acpi_ut_status_exit(__LINE__,&_dbg,(s));return((s));}) +#define return_VALUE(s) ACPI_DO_WHILE0 ({acpi_ut_value_exit(__LINE__,&_dbg,(acpi_integer)(s));return((s));}) +#define return_PTR(s) ACPI_DO_WHILE0 ({acpi_ut_ptr_exit(__LINE__,&_dbg,(u8 *)(s));return((s));}) /* Conditional execution */ @@ -427,7 +447,7 @@ #define ACPI_DUMP_ENTRY(a,b) acpi_ns_dump_entry (a,b) #define ACPI_DUMP_TABLES(a,b) acpi_ns_dump_tables(a,b) -#define ACPI_DUMP_PATHNAME(a,b,c,d) acpi_ns_dump_pathname(a,b,c,d) +#define ACPI_DUMP_PATHNAME(a,b,c,d) (void) acpi_ns_dump_pathname(a,b,c,d) #define ACPI_DUMP_RESOURCE_LIST(a) acpi_rs_dump_resource_list(a) #define ACPI_DUMP_BUFFER(a,b) acpi_ut_dump_buffer((u8 *)a,b,DB_BYTE_DISPLAY,_COMPONENT) #define ACPI_BREAK_MSG(a) acpi_os_signal (ACPI_SIGNAL_BREAKPOINT,(a)) @@ -495,6 +515,10 @@ #define return_VALUE(s) return(s) #define return_PTR(s) return(s) +#ifdef ENABLE_DEBUGGER +#define _OPCODE_NAMES +#endif + #endif /* @@ -513,7 +537,7 @@ * For 16-bit code, we want to shrink some things even though * we are using ACPI_DEBUG to get the debug output */ -#ifdef _IA16 +#if ACPI_MACHINE_WIDTH == 16 #undef ACPI_DEBUG_ONLY_MEMBERS #undef _VERBOSE_STRUCTURES #define ACPI_DEBUG_ONLY_MEMBERS(a) @@ -541,8 +565,8 @@ /* Memory allocation */ -#define ACPI_MEM_ALLOCATE(a) acpi_ut_allocate(a,_COMPONENT,_THIS_MODULE,__LINE__) -#define ACPI_MEM_CALLOCATE(a) acpi_ut_callocate(a, _COMPONENT,_THIS_MODULE,__LINE__) +#define ACPI_MEM_ALLOCATE(a) acpi_ut_allocate((ACPI_SIZE)(a),_COMPONENT,_THIS_MODULE,__LINE__) +#define ACPI_MEM_CALLOCATE(a) acpi_ut_callocate((ACPI_SIZE)(a), _COMPONENT,_THIS_MODULE,__LINE__) #define ACPI_MEM_FREE(a) acpi_os_free(a) #define ACPI_MEM_TRACKING(a) @@ -551,8 +575,8 @@ /* Memory allocation */ -#define ACPI_MEM_ALLOCATE(a) acpi_ut_allocate_and_track(a,_COMPONENT,_THIS_MODULE,__LINE__) -#define ACPI_MEM_CALLOCATE(a) acpi_ut_callocate_and_track(a, _COMPONENT,_THIS_MODULE,__LINE__) +#define ACPI_MEM_ALLOCATE(a) acpi_ut_allocate_and_track((ACPI_SIZE)(a),_COMPONENT,_THIS_MODULE,__LINE__) +#define ACPI_MEM_CALLOCATE(a) acpi_ut_callocate_and_track((ACPI_SIZE)(a), _COMPONENT,_THIS_MODULE,__LINE__) #define ACPI_MEM_FREE(a) acpi_ut_free_and_track(a,_COMPONENT,_THIS_MODULE,__LINE__) #define ACPI_MEM_TRACKING(a) a diff -Nru a/drivers/acpi/include/acnamesp.h b/drivers/acpi/include/acnamesp.h --- a/drivers/acpi/include/acnamesp.h Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/include/acnamesp.h Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acnamesp.h - Namespace subcomponent prototypes and defines - * $Revision: 123 $ + * $Revision: 125 $ * *****************************************************************************/ @@ -108,7 +108,7 @@ acpi_namespace_node *parent, acpi_namespace_node *child); -acpi_status +void acpi_ns_delete_namespace_by_owner ( u16 table_id); @@ -139,7 +139,6 @@ * Top-level namespace access - nsaccess */ - acpi_status acpi_ns_root_initialize ( void); @@ -159,7 +158,6 @@ * Named object allocation/deallocation - nsalloc */ - acpi_namespace_node * acpi_ns_create_node ( u32 name); @@ -168,7 +166,7 @@ acpi_ns_delete_node ( acpi_namespace_node *node); -acpi_status +void acpi_ns_delete_namespace_subtree ( acpi_namespace_node *parent_handle); @@ -220,10 +218,24 @@ u32 num_segments, char *pathname); +acpi_status +acpi_ns_dump_one_device ( + acpi_handle obj_handle, + u32 level, + void *context, + void **return_value); + void acpi_ns_dump_root_devices ( void); +acpi_status +acpi_ns_dump_one_object ( + acpi_handle obj_handle, + u32 level, + void *context, + void **return_value); + void acpi_ns_dump_objects ( acpi_object_type type, @@ -289,6 +301,12 @@ acpi_ns_opens_scope ( acpi_object_type type); +void +acpi_ns_build_external_path ( + acpi_namespace_node *node, + ACPI_SIZE size, + NATIVE_CHAR *name_buffer); + NATIVE_CHAR * acpi_ns_get_external_pathname ( acpi_namespace_node *node); @@ -408,7 +426,7 @@ acpi_ns_build_internal_name ( acpi_namestring_info *info); -acpi_status +void acpi_ns_get_internal_name_length ( acpi_namestring_info *info); diff -Nru a/drivers/acpi/include/acobject.h b/drivers/acpi/include/acobject.h --- a/drivers/acpi/include/acobject.h Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/include/acobject.h Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ /****************************************************************************** * * Name: acobject.h - Definition of acpi_operand_object (Internal object only) - * $Revision: 110 $ + * $Revision: 111 $ * *****************************************************************************/ @@ -481,5 +481,42 @@ ACPI_OBJECT_CACHE_LIST cache; } acpi_operand_object; + + +/****************************************************************************** + * + * ACPI_DESCRIPTOR - objects that share a common descriptor identifier + * + *****************************************************************************/ + + +/* Object descriptor types */ + +#define ACPI_DESC_TYPE_CACHED 0x11 /* Used only when object is cached */ +#define ACPI_DESC_TYPE_STATE 0x20 +#define ACPI_DESC_TYPE_STATE_UPDATE 0x21 +#define ACPI_DESC_TYPE_STATE_PACKAGE 0x22 +#define ACPI_DESC_TYPE_STATE_CONTROL 0x23 +#define ACPI_DESC_TYPE_STATE_RPSCOPE 0x24 +#define ACPI_DESC_TYPE_STATE_PSCOPE 0x25 +#define ACPI_DESC_TYPE_STATE_WSCOPE 0x26 +#define ACPI_DESC_TYPE_STATE_RESULT 0x27 +#define ACPI_DESC_TYPE_STATE_NOTIFY 0x28 +#define ACPI_DESC_TYPE_STATE_THREAD 0x29 +#define ACPI_DESC_TYPE_WALK 0x44 +#define ACPI_DESC_TYPE_PARSER 0x66 +#define ACPI_DESC_TYPE_OPERAND 0x88 +#define ACPI_DESC_TYPE_NAMED 0xAA + + +typedef union acpi_desc +{ + u8 descriptor_id; /* To differentiate various internal objs */\ + acpi_operand_object object; + acpi_namespace_node node; + acpi_parse_object op; + +} ACPI_DESCRIPTOR; + #endif /* _ACOBJECT_H */ diff -Nru a/drivers/acpi/include/acparser.h b/drivers/acpi/include/acparser.h --- a/drivers/acpi/include/acparser.h Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/include/acparser.h Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: acparser.h - AML Parser subcomponent prototypes and defines - * $Revision: 58 $ + * $Revision: 59 $ * *****************************************************************************/ @@ -134,7 +134,7 @@ acpi_ps_get_opcode_size ( u32 opcode); -u8 +void acpi_ps_complete_this_op ( acpi_walk_state *walk_state, acpi_parse_object *op); diff -Nru a/drivers/acpi/include/acpixf.h b/drivers/acpi/include/acpixf.h --- a/drivers/acpi/include/acpixf.h Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/include/acpixf.h Sun Jun 2 18:44:56 2002 @@ -71,6 +71,10 @@ acpi_purge_cached_objects ( void); +acpi_status +acpi_install_initialization_handler ( + ACPI_INIT_HANDLER handler, + u32 function); /* * ACPI Memory manager @@ -330,6 +334,18 @@ */ acpi_status +acpi_get_register ( + u32 register_id, + u32 *return_value, + u32 flags); + +acpi_status +acpi_set_register ( + u32 register_id, + u32 value, + u32 flags); + +acpi_status acpi_set_firmware_waking_vector ( ACPI_PHYSICAL_ADDRESS physical_address); @@ -337,17 +353,23 @@ acpi_get_firmware_waking_vector ( ACPI_PHYSICAL_ADDRESS *physical_address); +acpi_status +acpi_get_sleep_type_data ( + u8 sleep_state, + u8 *slp_typ_a, + u8 *slp_typ_b); acpi_status acpi_enter_sleep_state_prep ( - u8 sleep_state); + u8 sleep_state); acpi_status acpi_enter_sleep_state ( - u8 sleep_state); + u8 sleep_state); acpi_status acpi_leave_sleep_state ( - u8 sleep_state); + u8 sleep_state); + #endif /* __ACXFACE_H__ */ diff -Nru a/drivers/acpi/include/acresrc.h b/drivers/acpi/include/acresrc.h --- a/drivers/acpi/include/acresrc.h Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/include/acresrc.h Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acresrc.h - Resource Manager function prototypes - * $Revision: 30 $ + * $Revision: 33 $ * *****************************************************************************/ @@ -69,8 +69,59 @@ /* - *Function prototypes called from Acpi_rs_create* + * Function prototypes called from Acpi_rs_create* */ +void +acpi_rs_dump_irq ( + acpi_resource_data *data); + +void +acpi_rs_dump_address16 ( + acpi_resource_data *data); + +void +acpi_rs_dump_address32 ( + acpi_resource_data *data); + +void +acpi_rs_dump_address64 ( + acpi_resource_data *data); + +void +acpi_rs_dump_dma ( + acpi_resource_data *data); + +void +acpi_rs_dump_io ( + acpi_resource_data *data); + +void +acpi_rs_dump_extended_irq ( + acpi_resource_data *data); + +void +acpi_rs_dump_fixed_io ( + acpi_resource_data *data); + +void +acpi_rs_dump_fixed_memory32 ( + acpi_resource_data *data); + +void +acpi_rs_dump_memory24 ( + acpi_resource_data *data); + +void +acpi_rs_dump_memory32 ( + acpi_resource_data *data); + +void +acpi_rs_dump_start_depend_fns ( + acpi_resource_data *data); + +void +acpi_rs_dump_vendor_specific ( + acpi_resource_data *data); void acpi_rs_dump_resource_list ( @@ -87,18 +138,18 @@ u32 *size); acpi_status -acpi_rs_calculate_list_length ( +acpi_rs_get_list_length ( u8 *byte_stream_buffer, u32 byte_stream_buffer_length, ACPI_SIZE *size_needed); acpi_status -acpi_rs_calculate_byte_stream_length ( +acpi_rs_get_byte_stream_length ( acpi_resource *linked_list_buffer, ACPI_SIZE *size_needed); acpi_status -acpi_rs_calculate_pci_routing_table_length ( +acpi_rs_get_pci_routing_table_length ( acpi_operand_object *package_object, ACPI_SIZE *buffer_size_needed); @@ -111,7 +162,7 @@ acpi_status acpi_rs_list_to_byte_stream ( acpi_resource *linked_list, - u32 byte_stream_size_needed, + ACPI_SIZE byte_stream_size_needed, u8 *output_buffer); acpi_status diff -Nru a/drivers/acpi/include/acstruct.h b/drivers/acpi/include/acstruct.h --- a/drivers/acpi/include/acstruct.h Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/include/acstruct.h Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acstruct.h - Internal structs - * $Revision: 17 $ + * $Revision: 19 $ * *****************************************************************************/ @@ -39,12 +39,14 @@ * the tree (for whatever reason), and for control method execution. */ -#define ACPI_NEXT_OP_DOWNWARD 1 -#define ACPI_NEXT_OP_UPWARD 2 +#define ACPI_NEXT_OP_DOWNWARD 1 +#define ACPI_NEXT_OP_UPWARD 2 -#define ACPI_WALK_NON_METHOD 0 -#define ACPI_WALK_METHOD 1 -#define ACPI_WALK_METHOD_RESTART 2 +#define ACPI_WALK_NON_METHOD 0 +#define ACPI_WALK_METHOD 1 +#define ACPI_WALK_METHOD_RESTART 2 +#define ACPI_WALK_CONST_REQUIRED 3 +#define ACPI_WALK_CONST_OPTIONAL 4 typedef struct acpi_walk_state { @@ -102,6 +104,7 @@ typedef struct acpi_init_walk_info { u16 method_count; + u16 device_count; u16 op_region_count; u16 field_count; u16 buffer_count; diff -Nru a/drivers/acpi/include/actables.h b/drivers/acpi/include/actables.h --- a/drivers/acpi/include/actables.h Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/include/actables.h Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: actables.h - ACPI table management - * $Revision: 36 $ + * $Revision: 41 $ * *****************************************************************************/ @@ -63,6 +63,15 @@ * tbget - Table "get" routines */ +void +acpi_tb_table_override ( + acpi_table_desc *table_info); + +acpi_status +acpi_tb_get_table_with_override ( + ACPI_POINTER *address, + acpi_table_desc *table_info); + acpi_status acpi_tb_get_table_ptr ( acpi_table_type table_type, @@ -90,7 +99,7 @@ acpi_tb_get_table_pointer ( ACPI_POINTER *address, u32 flags, - u32 *size, + ACPI_SIZE *size, acpi_table_header **table_ptr); /* @@ -99,8 +108,7 @@ acpi_status acpi_tb_get_all_tables ( - u32 number_of_tables, - acpi_table_header *buffer_ptr); + u32 number_of_tables); /* @@ -109,7 +117,6 @@ acpi_status acpi_tb_install_table ( - acpi_table_header *table_ptr, acpi_table_desc *table_info); acpi_status @@ -119,7 +126,6 @@ acpi_status acpi_tb_recognize_table ( - acpi_table_header *table_ptr, acpi_table_desc *table_info); acpi_status @@ -186,7 +192,7 @@ acpi_status acpi_tb_map_acpi_table ( ACPI_PHYSICAL_ADDRESS physical_address, - u32 *size, + ACPI_SIZE *size, acpi_table_header **logical_address); acpi_status diff -Nru a/drivers/acpi/include/actypes.h b/drivers/acpi/include/actypes.h --- a/drivers/acpi/include/actypes.h Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/include/actypes.h Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: actypes.h - Common data types for the entire ACPI subsystem - * $Revision: 227 $ + * $Revision: 237 $ * *****************************************************************************/ @@ -28,13 +28,23 @@ /*! [Begin] no source code translation (keep the typedefs) */ + + +/* + * Data type ranges + */ +#define ACPI_UINT8_MAX (UINT8) 0xFF +#define ACPI_UINT16_MAX (UINT16) 0xFFFF +#define ACPI_UINT32_MAX (UINT32) 0xFFFFFFFF +#define ACPI_UINT64_MAX (UINT64) 0xFFFFFFFFFFFFFFFF +#define ACPI_ASCII_MAX 0x7F + + + /* * Data types - Fixed across all compilation models * * BOOLEAN Logical Boolean. - * 1 byte value containing a 0 for FALSE or a 1 for TRUE. - * Other values are undefined. - * * INT8 8-bit (1 byte) signed value * UINT8 8-bit (1 byte) unsigned value * INT16 16-bit (2 byte) signed value @@ -47,8 +57,11 @@ * NATIVE_UINT 32-bit on IA-32, 64-bit on IA-64 unsigned value */ +#ifndef ACPI_MACHINE_WIDTH +#error ACPI_MACHINE_WIDTH not defined +#endif -#ifdef _IA64 +#if ACPI_MACHINE_WIDTH == 64 /* * 64-bit type definitions */ @@ -60,8 +73,11 @@ typedef COMPILER_DEPENDENT_INT64 INT64; typedef COMPILER_DEPENDENT_UINT64 UINT64; +typedef INT64 NATIVE_INT; typedef UINT64 NATIVE_UINT; -typedef UINT64 NATIVE_INT; + +typedef UINT32 NATIVE_UINT_MAX32; +typedef UINT64 NATIVE_UINT_MIN32; typedef UINT64 ACPI_TBLPTR; typedef UINT64 ACPI_IO_ADDRESS; @@ -70,10 +86,11 @@ #define ALIGNED_ADDRESS_BOUNDARY 0x00000008 /* No hardware alignment support in IA64 */ #define ACPI_USE_NATIVE_DIVIDE /* Native 64-bit integer support */ -#define ACPI_MAX_PTR 0xFFFFFFFFFFFFFFFF +#define ACPI_MAX_PTR ACPI_UINT64_MAX +#define ACPI_SIZE_MAX ACPI_UINT64_MAX -#elif _IA16 +#elif ACPI_MACHINE_WIDTH == 16 /* * 16-bit type definitions */ @@ -94,15 +111,19 @@ typedef UINT16 NATIVE_UINT; typedef INT16 NATIVE_INT; +typedef UINT16 NATIVE_UINT_MAX32; +typedef UINT32 NATIVE_UINT_MIN32; + typedef UINT32 ACPI_TBLPTR; typedef UINT32 ACPI_IO_ADDRESS; typedef char *ACPI_PHYSICAL_ADDRESS; -typedef UINT32 ACPI_SIZE; +typedef UINT16 ACPI_SIZE; #define ALIGNED_ADDRESS_BOUNDARY 0x00000002 #define _HW_ALIGNMENT_SUPPORT #define ACPI_USE_NATIVE_DIVIDE /* No 64-bit integers, ok to use native divide */ -#define ACPI_MAX_PTR 0xFFFF +#define ACPI_MAX_PTR ACPI_UINT16_MAX +#define ACPI_SIZE_MAX ACPI_UINT16_MAX /* * (16-bit only) internal integers must be 32-bits, so @@ -111,7 +132,7 @@ #define ACPI_NO_INTEGER64_SUPPORT -#else +#elif ACPI_MACHINE_WIDTH == 32 /* * 32-bit type definitions (default) */ @@ -123,8 +144,11 @@ typedef COMPILER_DEPENDENT_INT64 INT64; typedef COMPILER_DEPENDENT_UINT64 UINT64; -typedef UINT32 NATIVE_UINT; typedef INT32 NATIVE_INT; +typedef UINT32 NATIVE_UINT; + +typedef UINT32 NATIVE_UINT_MAX32; +typedef UINT32 NATIVE_UINT_MIN32; typedef UINT64 ACPI_TBLPTR; typedef UINT32 ACPI_IO_ADDRESS; @@ -133,9 +157,12 @@ #define ALIGNED_ADDRESS_BOUNDARY 0x00000004 #define _HW_ALIGNMENT_SUPPORT -#define ACPI_MAX_PTR 0xFFFFFFFF -#endif +#define ACPI_MAX_PTR ACPI_UINT32_MAX +#define ACPI_SIZE_MAX ACPI_UINT32_MAX +#else +#error unknown ACPI_MACHINE_WIDTH +#endif /* @@ -147,16 +174,6 @@ typedef char NATIVE_CHAR; -/* - * Data type ranges - */ -#define ACPI_UINT8_MAX (UINT8) 0xFF -#define ACPI_UINT16_MAX (UINT16) 0xFFFF -#define ACPI_UINT32_MAX (UINT32) 0xFFFFFFFF -#define ACPI_UINT64_MAX (UINT64) 0xFFFFFFFFFFFFFFFF -#define ACPI_ASCII_MAX 0x7F - - #ifdef DEFINE_ALTERNATE_TYPES /* * Types used only in translated source, defined here to enable @@ -175,7 +192,7 @@ * Pointer overlays to avoid lots of typecasting for * code that accepts both physical and logical pointers. */ -typedef union acpi_pointers +typedef union acpi_ptrs { ACPI_PHYSICAL_ADDRESS physical; void *logical; @@ -186,7 +203,7 @@ typedef struct acpi_pointer { u32 pointer_type; - ACPI_POINTERS pointer; + union acpi_ptrs pointer; } ACPI_POINTER; @@ -238,6 +255,13 @@ } uint64_overlay; +typedef struct +{ + u32 lo; + u32 hi; + +} UINT32_STRUCT; + /* * Acpi integer width. In ACPI version 1, integers are @@ -271,7 +295,7 @@ #define ACPI_MAX_BCD_DIGITS 16 #define ACPI_MAX_DECIMAL_DIGITS 19 -#ifdef _IA64 +#if ACPI_MACHINE_WIDTH == 64 #define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 64-bit divide */ #endif #endif @@ -281,7 +305,7 @@ * Constants with special meanings */ -#define ACPI_ROOT_OBJECT (acpi_handle) ACPI_PTR_ADD (char, NULL, ACPI_UINT32_MAX) +#define ACPI_ROOT_OBJECT (acpi_handle) ACPI_PTR_ADD (char, NULL, ACPI_MAX_PTR) /* @@ -562,6 +586,37 @@ /* + * Bit_register IDs + * These are bitfields defined within the full ACPI registers + */ +#define ACPI_BITREG_TIMER_STATUS 0x00 +#define ACPI_BITREG_BUS_MASTER_STATUS 0x01 +#define ACPI_BITREG_GLOBAL_LOCK_STATUS 0x02 +#define ACPI_BITREG_POWER_BUTTON_STATUS 0x03 +#define ACPI_BITREG_SLEEP_BUTTON_STATUS 0x04 +#define ACPI_BITREG_RT_CLOCK_STATUS 0x05 +#define ACPI_BITREG_WAKE_STATUS 0x06 + +#define ACPI_BITREG_TIMER_ENABLE 0x07 +#define ACPI_BITREG_GLOBAL_LOCK_ENABLE 0x08 +#define ACPI_BITREG_POWER_BUTTON_ENABLE 0x09 +#define ACPI_BITREG_SLEEP_BUTTON_ENABLE 0x0A +#define ACPI_BITREG_RT_CLOCK_ENABLE 0x0B +#define ACPI_BITREG_WAKE_ENABLE 0x0C + +#define ACPI_BITREG_SCI_ENABLE 0x0D +#define ACPI_BITREG_BUS_MASTER_RLD 0x0E +#define ACPI_BITREG_GLOBAL_LOCK_RELEASE 0x0F +#define ACPI_BITREG_SLEEP_TYPE_A 0x10 +#define ACPI_BITREG_SLEEP_TYPE_B 0x11 +#define ACPI_BITREG_SLEEP_ENABLE 0x12 + +#define ACPI_BITREG_ARB_DISABLE 0x13 + +#define ACPI_BITREG_MAX 0x13 +#define ACPI_NUM_BITREG ACPI_BITREG_MAX + 1 + +/* * External ACPI object definition */ @@ -720,6 +775,13 @@ u32 function, void *data); +typedef +acpi_status (*ACPI_INIT_HANDLER) ( + acpi_handle object, + u32 function); + +#define ACPI_INIT_DEVICE_INI 1 + /* Address Spaces (Operation Regions */ @@ -732,7 +794,7 @@ void *handler_context, void *region_context); -#define ACPI_DEFAULT_HANDLER ((acpi_adr_space_handler) NULL) +#define ACPI_DEFAULT_HANDLER NULL typedef @@ -807,7 +869,7 @@ ACPI_PHYSICAL_ADDRESS address; ACPI_PHYSICAL_ADDRESS mapped_physical_address; u8 *mapped_logical_address; - u32 mapped_length; + ACPI_SIZE mapped_length; } acpi_mem_space_context; diff -Nru a/drivers/acpi/include/acutils.h b/drivers/acpi/include/acutils.h --- a/drivers/acpi/include/acutils.h Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/include/acutils.h Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acutils.h -- prototypes for the common (subsystem-wide) procedures - * $Revision: 130 $ + * $Revision: 137 $ * *****************************************************************************/ @@ -82,7 +82,7 @@ acpi_ut_hardware_initialize ( void); -acpi_status +void acpi_ut_subsystem_shutdown ( void); @@ -94,7 +94,7 @@ * Ut_global - Global data structures and procedures */ -#ifdef ACPI_DEBUG +#if defined(ACPI_DEBUG) || defined(ENABLE_DEBUGGER) NATIVE_CHAR * acpi_ut_get_mutex_name ( @@ -115,7 +115,7 @@ acpi_ut_get_event_name ( u32 event_id); -u8 +char acpi_ut_hex_to_ascii_char ( acpi_integer integer, u32 position); @@ -150,7 +150,7 @@ const NATIVE_CHAR *src_string, NATIVE_UINT count); -u32 +int acpi_ut_strncmp ( const NATIVE_CHAR *string1, const NATIVE_CHAR *string2, @@ -195,13 +195,32 @@ NATIVE_UINT value, NATIVE_UINT count); -u32 +int acpi_ut_to_upper ( - u32 c); + int c); -u32 +int acpi_ut_to_lower ( - u32 c); + int c); + +extern const u8 _acpi_ctype[]; + +#define _ACPI_XA 0x00 /* extra alphabetic - not supported */ +#define _ACPI_XS 0x40 /* extra space */ +#define _ACPI_BB 0x00 /* BEL, BS, etc. - not supported */ +#define _ACPI_CN 0x20 /* CR, FF, HT, NL, VT */ +#define _ACPI_DI 0x04 /* '0'-'9' */ +#define _ACPI_LO 0x02 /* 'a'-'z' */ +#define _ACPI_PU 0x10 /* punctuation */ +#define _ACPI_SP 0x08 /* space */ +#define _ACPI_UP 0x01 /* 'A'-'Z' */ +#define _ACPI_XD 0x80 /* '0'-'9', 'A'-'F', 'a'-'f' */ + +#define ACPI_IS_DIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_DI)) +#define ACPI_IS_SPACE(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_SP)) +#define ACPI_IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD)) +#define ACPI_IS_UPPER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP)) +#define ACPI_IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO)) #endif /* ACPI_USE_SYSTEM_CLIBRARY */ @@ -223,6 +242,20 @@ u32 *space_used); acpi_status +acpi_ut_copy_ielement_to_eelement ( + u8 object_type, + acpi_operand_object *source_object, + acpi_generic_state *state, + void *context); + +acpi_status +acpi_ut_copy_ielement_to_ielement ( + u8 object_type, + acpi_operand_object *source_object, + acpi_generic_state *state, + void *context); + +acpi_status acpi_ut_copy_iobject_to_eobject ( acpi_operand_object *obj, acpi_buffer *ret_buffer); @@ -386,7 +419,7 @@ acpi_ut_delete_internal_simple_object ( acpi_operand_object *object); -acpi_status +void acpi_ut_delete_internal_object_list ( acpi_operand_object **obj_list); @@ -524,6 +557,13 @@ acpi_operand_object *obj, ACPI_SIZE *obj_length); +acpi_status +acpi_ut_get_element_length ( + u8 object_type, + acpi_operand_object *source_object, + acpi_generic_state *state, + void *context); + /* * Ut_state - Generic state creation/cache routines @@ -613,6 +653,12 @@ acpi_ut_valid_acpi_character ( NATIVE_CHAR character); +acpi_status +acpi_ut_strtoul64 ( + NATIVE_CHAR *string, + u32 base, + acpi_integer *ret_integer); + NATIVE_CHAR * acpi_ut_strupr ( NATIVE_CHAR *src_string); @@ -621,6 +667,13 @@ acpi_ut_resolve_package_references ( acpi_operand_object *obj_desc); +acpi_status +acpi_ut_resolve_reference ( + u8 object_type, + acpi_operand_object *source_object, + acpi_generic_state *state, + void *context); + u8 * acpi_ut_get_resource_end_tag ( acpi_operand_object *obj_desc); @@ -630,6 +683,14 @@ u8 *buffer, u32 length); +u32 +acpi_ut_dword_byte_swap ( + u32 value); + +void +acpi_ut_set_integer_width ( + u8 revision); + #ifdef ACPI_DEBUG void acpi_ut_display_init_pathname ( @@ -705,6 +766,12 @@ u32 component, NATIVE_CHAR *module, u32 line); + +acpi_debug_mem_block * +acpi_ut_find_allocation ( + u32 list_id, + void *allocation); + acpi_status acpi_ut_track_allocation ( u32 list_id, diff -Nru a/drivers/acpi/include/amlcode.h b/drivers/acpi/include/amlcode.h --- a/drivers/acpi/include/amlcode.h Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/include/amlcode.h Sun Jun 2 18:44:58 2002 @@ -3,7 +3,7 @@ * Name: amlcode.h - Definitions for AML, as included in "definition blocks" * Declarations and definitions contained herein are derived * directly from the ACPI specification. - * $Revision: 67 $ + * $Revision: 68 $ * *****************************************************************************/ @@ -28,7 +28,6 @@ #ifndef __AMLCODE_H__ #define __AMLCODE_H__ - /* primary opcodes */ #define AML_NULL_CHAR (u16) 0x00 @@ -290,6 +289,7 @@ #define AML_CREATE 0x0004 #define AML_MATH 0x0002 #define AML_LOGICAL 0x0001 +#define AML_CONSTANT 0x1000 /* Convenient flag groupings */ diff -Nru a/drivers/acpi/include/platform/acenv.h b/drivers/acpi/include/platform/acenv.h --- a/drivers/acpi/include/platform/acenv.h Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/include/platform/acenv.h Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acenv.h - Generation environment specific items - * $Revision: 86 $ + * $Revision: 94 $ * *****************************************************************************/ @@ -51,7 +51,7 @@ #ifdef _ACPI_ASL_COMPILER #define ACPI_DEBUG #define ACPI_APPLICATION -#define ENABLE_DEBUGGER +/* #define ENABLE_DEBUGGER */ #define ACPI_USE_SYSTEM_CLIBRARY #endif @@ -61,7 +61,7 @@ * 2) This is NOT a 16-bit version of the code (not enough real-mode memory) */ #ifdef ACPI_DEBUG -#ifndef _IA16 +#if ACPI_MACHINE_WIDTH != 16 #define ACPI_DBG_TRACK_ALLOCATIONS #endif #endif @@ -111,15 +111,15 @@ #elif defined(_AED_EFI) #include "acefi.h" -#elif defined(MSDOS) -#include "acdos16.h" - #elif defined(WIN32) #include "acwin.h" #elif defined(WIN64) #include "acwin64.h" +#elif defined(MSDOS) /* Must appear after WIN32 and WIN64 check */ +#include "acdos16.h" + #elif defined(__FreeBSD__) #include "acfreebsd.h" @@ -135,6 +135,10 @@ #define ACPI_USE_STANDARD_HEADERS +#define COMPILER_DEPENDENT_INT64 long long +#define COMPILER_DEPENDENT_UINT64 unsigned long long + + /* Name of host operating system (returned by the _OS_ namespace object) */ #define ACPI_OS_NAME "Intel ACPI/CA Core Subsystem" @@ -178,20 +182,23 @@ */ #define ACPI_STRSTR(s1,s2) strstr((s1), (s2)) -#define ACPI_STRUPR(s) acpi_ut_strupr ((s)) -#define ACPI_STRLEN(s) (u32) strlen((s)) -#define ACPI_STRCPY(d,s) strcpy((d), (s)) -#define ACPI_STRNCPY(d,s,n) strncpy((d), (s), (NATIVE_INT)(n)) -#define ACPI_STRNCMP(d,s,n) strncmp((d), (s), (NATIVE_INT)(n)) +#define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s)) +#define ACPI_STRLEN(s) (ACPI_SIZE) strlen((s)) +#define ACPI_STRCPY(d,s) (void) strcpy((d), (s)) +#define ACPI_STRNCPY(d,s,n) (void) strncpy((d), (s), (ACPI_SIZE)(n)) +#define ACPI_STRNCMP(d,s,n) strncmp((d), (s), (ACPI_SIZE)(n)) #define ACPI_STRCMP(d,s) strcmp((d), (s)) -#define ACPI_STRCAT(d,s) strcat((d), (s)) -#define ACPI_STRNCAT(d,s,n) strncat((d), (s), (NATIVE_INT)(n)) -#define ACPI_STRTOUL(d,s,n) strtoul((d), (s), (NATIVE_INT)(n)) -#define ACPI_MEMCPY(d,s,n) (void) memcpy((d), (s), (NATIVE_INT)(n)) -#define ACPI_MEMSET(d,s,n) (void) memset((d), (s), (NATIVE_INT)(n)) +#define ACPI_STRCAT(d,s) (void) strcat((d), (s)) +#define ACPI_STRNCAT(d,s,n) strncat((d), (s), (ACPI_SIZE)(n)) +#define ACPI_STRTOUL(d,s,n) strtoul((d), (s), (ACPI_SIZE)(n)) +#define ACPI_MEMCPY(d,s,n) (void) memcpy((d), (s), (ACPI_SIZE)(n)) +#define ACPI_MEMSET(d,s,n) (void) memset((d), (s), (ACPI_SIZE)(n)) #define ACPI_TOUPPER toupper #define ACPI_TOLOWER tolower #define ACPI_IS_XDIGIT isxdigit +#define ACPI_IS_DIGIT isdigit +#define ACPI_IS_SPACE isspace +#define ACPI_IS_UPPER isupper /****************************************************************************** * @@ -234,17 +241,17 @@ #define ACPI_STRSTR(s1,s2) acpi_ut_strstr ((s1), (s2)) -#define ACPI_STRUPR(s) acpi_ut_strupr ((s)) -#define ACPI_STRLEN(s) acpi_ut_strlen ((s)) -#define ACPI_STRCPY(d,s) acpi_ut_strcpy ((d), (s)) -#define ACPI_STRNCPY(d,s,n) acpi_ut_strncpy ((d), (s), (n)) -#define ACPI_STRNCMP(d,s,n) acpi_ut_strncmp ((d), (s), (n)) +#define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s)) +#define ACPI_STRLEN(s) (ACPI_SIZE) acpi_ut_strlen ((s)) +#define ACPI_STRCPY(d,s) (void) acpi_ut_strcpy ((d), (s)) +#define ACPI_STRNCPY(d,s,n) (void) acpi_ut_strncpy ((d), (s), (ACPI_SIZE)(n)) +#define ACPI_STRNCMP(d,s,n) acpi_ut_strncmp ((d), (s), (ACPI_SIZE)(n)) #define ACPI_STRCMP(d,s) acpi_ut_strcmp ((d), (s)) -#define ACPI_STRCAT(d,s) acpi_ut_strcat ((d), (s)) -#define ACPI_STRNCAT(d,s,n) acpi_ut_strncat ((d), (s), (n)) -#define ACPI_STRTOUL(d,s,n) acpi_ut_strtoul ((d), (s),(n)) -#define ACPI_MEMCPY(d,s,n) (void) acpi_ut_memcpy ((d), (s), (n)) -#define ACPI_MEMSET(d,v,n) (void) acpi_ut_memset ((d), (v), (n)) +#define ACPI_STRCAT(d,s) (void) acpi_ut_strcat ((d), (s)) +#define ACPI_STRNCAT(d,s,n) acpi_ut_strncat ((d), (s), (ACPI_SIZE)(n)) +#define ACPI_STRTOUL(d,s,n) acpi_ut_strtoul ((d), (s), (ACPI_SIZE)(n)) +#define ACPI_MEMCPY(d,s,n) (void) acpi_ut_memcpy ((d), (s), (ACPI_SIZE)(n)) +#define ACPI_MEMSET(d,v,n) (void) acpi_ut_memset ((d), (v), (ACPI_SIZE)(n)) #define ACPI_TOUPPER acpi_ut_to_upper #define ACPI_TOLOWER acpi_ut_to_lower diff -Nru a/drivers/acpi/include/platform/acgcc.h b/drivers/acpi/include/platform/acgcc.h --- a/drivers/acpi/include/platform/acgcc.h Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/include/platform/acgcc.h Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acgcc.h - GCC specific defines, etc. - * $Revision: 22 $ + * $Revision: 23 $ * *****************************************************************************/ @@ -25,172 +25,6 @@ #ifndef __ACGCC_H__ #define __ACGCC_H__ - - -#ifdef __ia64__ -#define _IA64 - -#define COMPILER_DEPENDENT_INT64 long -#define COMPILER_DEPENDENT_UINT64 unsigned long - -/* - * Calling conventions: - * - * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) - * ACPI_EXTERNAL_XFACE - External ACPI interfaces - * ACPI_INTERNAL_XFACE - Internal ACPI interfaces - * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces - */ -#define ACPI_SYSTEM_XFACE -#define ACPI_EXTERNAL_XFACE -#define ACPI_INTERNAL_XFACE -#define ACPI_INTERNAL_VAR_XFACE - -/* Single threaded */ - -#define ACPI_APPLICATION - -/* Asm macros */ - -#define ACPI_ASM_MACROS -#define BREAKPOINT3 -#define ACPI_DISABLE_IRQS() __cli() -#define ACPI_ENABLE_IRQS() __sti() - -/*! [Begin] no source code translation */ - -#include - -#define halt() ia64_pal_halt_light() /* PAL_HALT[_LIGHT] */ -#define safe_halt() ia64_pal_halt(1) /* PAL_HALT */ - - -#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - __asm__ volatile ("1: ld4 r29=%1\n" \ - ";;\n" \ - "mov ar.ccv=r29\n" \ - "mov r2=r29\n" \ - "shr.u r30=r29,1\n" \ - "and r29=-4,r29\n" \ - ";;\n" \ - "add r29=2,r29\n" \ - "and r30=1,r30\n" \ - ";;\n" \ - "add r29=r29,r30\n" \ - ";;\n" \ - "cmpxchg4.acq r30=%1,r29,ar.ccv\n" \ - ";;\n" \ - "cmp.eq p6,p7=r2,r30\n" \ - "(p7) br.dpnt.few 1b\n" \ - "cmp.gt p8,p9=3,r29\n" \ - ";;\n" \ - "(p8) mov %0=-1\n" \ - "(p9) mov %0=r0\n" \ - :"=r"(Acq):"m"(GLptr):"r2","r29","r30","memory"); \ - } while (0) - -#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - __asm__ volatile ("1: ld4 r29=%1\n" \ - ";;\n" \ - "mov ar.ccv=r29\n" \ - "mov r2=r29\n" \ - "and r29=-4,r29\n" \ - ";;\n" \ - "cmpxchg4.acq r30=%1,r29,ar.ccv\n" \ - ";;\n" \ - "cmp.eq p6,p7=r2,r30\n" \ - "(p7) br.dpnt.few 1b\n" \ - "and %0=1,r2\n" \ - ";;\n" \ - :"=r"(Acq):"m"(GLptr):"r2","r29","r30","memory"); \ - } while (0) -/*! [End] no source code translation !*/ - - -#else /* DO IA32 */ - -#define COMPILER_DEPENDENT_INT64 long long -#define COMPILER_DEPENDENT_UINT64 unsigned long long - -/* - * Calling conventions: - * - * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) - * ACPI_EXTERNAL_XFACE - External ACPI interfaces - * ACPI_INTERNAL_XFACE - Internal ACPI interfaces - * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces - */ -#define ACPI_SYSTEM_XFACE -#define ACPI_EXTERNAL_XFACE -#define ACPI_INTERNAL_XFACE -#define ACPI_INTERNAL_VAR_XFACE - -/* Asm macros */ - -#define ACPI_ASM_MACROS -#define BREAKPOINT3 -#define ACPI_DISABLE_IRQS() __cli() -#define ACPI_ENABLE_IRQS() __sti() - -/*! [Begin] no source code translation - * - * A brief explanation as GNU inline assembly is a bit hairy - * %0 is the output parameter in EAX ("=a") - * %1 and %2 are the input parameters in ECX ("c") - * and an immediate value ("i") respectively - * All actual register references are preceded with "%%" as in "%%edx" - * Immediate values in the assembly are preceded by "$" as in "$0x1" - * The final asm parameter are the operation altered non-output registers. - */ -#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - int dummy; \ - asm("1: movl (%1),%%eax;" \ - "movl %%eax,%%edx;" \ - "andl %2,%%edx;" \ - "btsl $0x1,%%edx;" \ - "adcl $0x0,%%edx;" \ - "lock; cmpxchgl %%edx,(%1);" \ - "jnz 1b;" \ - "cmpb $0x3,%%dl;" \ - "sbbl %%eax,%%eax" \ - :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~1L):"dx"); \ - } while(0) - -#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - int dummy; \ - asm("1: movl (%1),%%eax;" \ - "movl %%eax,%%edx;" \ - "andl %2,%%edx;" \ - "lock; cmpxchgl %%edx,(%1);" \ - "jnz 1b;" \ - "andl $0x1,%%eax" \ - :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~3L):"dx"); \ - } while(0) - - -/* - * Math helper asm macros - */ -#define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) \ - asm("divl %2;" \ - :"=a"(q32), "=d"(r32) \ - :"r"(d32), \ - "0"(n_lo), "1"(n_hi)) - - -#define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \ - asm("shrl $1,%2;" \ - "rcrl $1,%3;" \ - :"=r"(n_hi), "=r"(n_lo) \ - :"0"(n_hi), "1"(n_lo)) - -/*! [End] no source code translation !*/ - -#endif /* IA 32 */ /* This macro is used to tag functions as "printf-like" because * some compilers (like GCC) can catch printf format string problems. diff -Nru a/drivers/acpi/include/platform/aclinux.h b/drivers/acpi/include/platform/aclinux.h --- a/drivers/acpi/include/platform/aclinux.h Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/include/platform/aclinux.h Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: aclinux.h - OS specific defines, etc. - * $Revision: 19 $ + * $Revision: 25 $ * *****************************************************************************/ @@ -39,14 +39,11 @@ #include #include #include +#include #define strtoul simple_strtoul -#ifdef _IA64 -#define ACPI_FLUSH_CPU_CACHE() -#else -#define ACPI_FLUSH_CPU_CACHE() wbinvd() -#endif +#define ACPI_MACHINE_WIDTH BITS_PER_LONG #else /* !__KERNEL__ */ @@ -55,6 +52,17 @@ #include #include +#if defined(__ia64__) || defined(__x86_64__) +#define ACPI_MACHINE_WIDTH 64 +#define COMPILER_DEPENDENT_INT64 long +#define COMPILER_DEPENDENT_UINT64 unsigned long +#else +#define ACPI_MACHINE_WIDTH 32 +#define COMPILER_DEPENDENT_INT64 long long +#define COMPILER_DEPENDENT_UINT64 unsigned long long +#define ACPI_USE_NATIVE_DIVIDE +#endif + #endif /* __KERNEL__ */ /* Linux uses GCC */ @@ -62,7 +70,6 @@ #include "acgcc.h" #undef DEBUGGER_THREADING -#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED - +#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED #endif /* __ACLINUX_H__ */ diff -Nru a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c --- a/drivers/acpi/namespace/nsaccess.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/namespace/nsaccess.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: nsaccess - Top-level functions for accessing ACPI namespace - * $Revision: 153 $ + * $Revision: 155 $ * ******************************************************************************/ @@ -26,7 +26,6 @@ #include "acpi.h" #include "amlcode.h" -#include "acinterp.h" #include "acnamesp.h" #include "acdispat.h" @@ -180,7 +179,7 @@ /* Store pointer to value descriptor in the Node */ - acpi_ns_attach_object (new_node, obj_desc, obj_desc->common.type); + status = acpi_ns_attach_object (new_node, obj_desc, obj_desc->common.type); /* Remove local reference to the object */ @@ -298,9 +297,10 @@ num_segments = 0; this_node = acpi_gbl_root_node; + pathname = ""; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, - "Null Pathname (Zero segments), Flags=%x\n", flags)); + "Null Pathname (Zero segments), Flags=%X\n", flags)); } else { /* @@ -316,7 +316,7 @@ * Parent Prefixes (in which case the name's scope is relative * to the current scope). */ - if (*pathname == AML_ROOT_PREFIX) { + if (*pathname == (u8) AML_ROOT_PREFIX) { /* Pathname is fully qualified, start from the root */ this_node = acpi_gbl_root_node; @@ -340,7 +340,7 @@ * the parent node for each prefix instance. */ this_node = prefix_node; - while (*pathname == AML_PARENT_PREFIX) { + while (*pathname == (u8) AML_PARENT_PREFIX) { /* * Point past this prefix to the name segment * part or the next Parent Prefix @@ -382,7 +382,7 @@ num_segments = 0; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, - "Prefix-only Pathname (Zero name segments), Flags=%x\n", flags)); + "Prefix-only Pathname (Zero name segments), Flags=%X\n", flags)); break; case AML_DUAL_NAME_PREFIX: diff -Nru a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c --- a/drivers/acpi/namespace/nsalloc.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/namespace/nsalloc.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: nsalloc - Namespace allocation and deletion utilities - * $Revision: 72 $ + * $Revision: 74 $ * ******************************************************************************/ @@ -26,7 +26,6 @@ #include "acpi.h" #include "acnamesp.h" -#include "acinterp.h" #define _COMPONENT ACPI_NAMESPACE @@ -207,7 +206,7 @@ * real definition is found later. */ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[%4.4s] is a forward reference\n", - (char *) &node->name)); + node->name.ascii)); } /* @@ -232,7 +231,7 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%4.4s added to %p at %p\n", - (char *) &node->name, parent_node, node)); + node->name.ascii, parent_node, node)); /* * Increment the reference count(s) of all parents up to @@ -339,7 +338,7 @@ * ******************************************************************************/ -acpi_status +void acpi_ns_delete_namespace_subtree ( acpi_namespace_node *parent_node) { @@ -351,7 +350,7 @@ if (!parent_node) { - return_ACPI_STATUS (AE_OK); + return_VOID; } /* @@ -403,7 +402,7 @@ } } - return_ACPI_STATUS (AE_OK); + return_VOID; } @@ -475,7 +474,7 @@ * ******************************************************************************/ -acpi_status +void acpi_ns_delete_namespace_by_owner ( u16 owner_id) { @@ -553,7 +552,7 @@ } } - return_ACPI_STATUS (AE_OK); + return_VOID; } diff -Nru a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c --- a/drivers/acpi/namespace/nsdump.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/namespace/nsdump.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: nsdump - table dumping routines for debug - * $Revision: 129 $ + * $Revision: 135 $ * *****************************************************************************/ @@ -25,9 +25,7 @@ #include "acpi.h" -#include "acinterp.h" #include "acnamesp.h" -#include "actables.h" #include "acparser.h" @@ -202,11 +200,11 @@ } else { if (acpi_ns_exist_downstream_sibling (this_node + 1)) { - downstream_sibling_mask |= (1 << (level - 1)); + downstream_sibling_mask |= ((u32) 1 << (level - 1)); acpi_os_printf ("+"); } else { - downstream_sibling_mask &= ACPI_UINT32_MAX ^ (1 << (level - 1)); + downstream_sibling_mask &= ACPI_UINT32_MAX ^ ((u32) 1 << (level - 1)); acpi_os_printf ("+"); } @@ -229,14 +227,14 @@ } if (!acpi_ut_valid_acpi_name (this_node->name.integer)) { - ACPI_REPORT_WARNING (("Invalid ACPI Name %08X\n", this_node->name)); + ACPI_REPORT_WARNING (("Invalid ACPI Name %08X\n", this_node->name.integer)); } /* * Now we can print out the pertinent information */ acpi_os_printf (" %4.4s %-12s %p", - (char *) &this_node->name, acpi_ut_get_type_name (type), this_node); + this_node->name.ascii, acpi_ut_get_type_name (type), this_node); dbg_level = acpi_dbg_level; acpi_dbg_level = 0; @@ -256,7 +254,7 @@ switch (type) { case ACPI_TYPE_PROCESSOR: - acpi_os_printf (" ID %d Addr %.4X Len %.4X\n", + acpi_os_printf (" ID %hd Addr %.4X Len %.4X\n", obj_desc->processor.proc_id, obj_desc->processor.address, obj_desc->processor.length); @@ -271,7 +269,7 @@ case ACPI_TYPE_METHOD: - acpi_os_printf (" Args %d Len %.4X Aml %p \n", + acpi_os_printf (" Args %hd Len %.4X Aml %p \n", obj_desc->method.param_count, obj_desc->method.aml_length, obj_desc->method.aml_start); @@ -309,7 +307,7 @@ if (obj_desc->buffer.length > 0) { acpi_os_printf (" ="); for (i = 0; (i < obj_desc->buffer.length && i < 12); i++) { - acpi_os_printf (" %.2X", obj_desc->buffer.pointer[i]); + acpi_os_printf (" %.2hX", obj_desc->buffer.pointer[i]); } } acpi_os_printf ("\n"); @@ -361,7 +359,7 @@ if (obj_desc->buffer_field.buffer_obj && obj_desc->buffer_field.buffer_obj->buffer.node) { acpi_os_printf (" Buf [%4.4s]", - (char *) &obj_desc->buffer_field.buffer_obj->buffer.node->name); + obj_desc->buffer_field.buffer_obj->buffer.node->name.ascii); } break; @@ -369,23 +367,23 @@ case INTERNAL_TYPE_REGION_FIELD: acpi_os_printf (" Rgn [%4.4s]", - (char *) &obj_desc->common_field.region_obj->region.node->name); + obj_desc->common_field.region_obj->region.node->name.ascii); break; case INTERNAL_TYPE_BANK_FIELD: acpi_os_printf (" Rgn [%4.4s] Bnk [%4.4s]", - (char *) &obj_desc->common_field.region_obj->region.node->name, - (char *) &obj_desc->bank_field.bank_obj->common_field.node->name); + obj_desc->common_field.region_obj->region.node->name.ascii, + obj_desc->bank_field.bank_obj->common_field.node->name.ascii); break; case INTERNAL_TYPE_INDEX_FIELD: acpi_os_printf (" Idx [%4.4s] Dat [%4.4s]", - (char *) &obj_desc->index_field.index_obj->common_field.node->name, - (char *) &obj_desc->index_field.data_obj->common_field.node->name); + obj_desc->index_field.index_obj->common_field.node->name.ascii, + obj_desc->index_field.data_obj->common_field.node->name.ascii); break; @@ -402,14 +400,16 @@ case INTERNAL_TYPE_REGION_FIELD: case INTERNAL_TYPE_BANK_FIELD: case INTERNAL_TYPE_INDEX_FIELD: - acpi_os_printf (" Off %.2X Len %.2X Acc %.2d\n", + acpi_os_printf (" Off %.2X Len %.2X Acc %.2hd\n", (obj_desc->common_field.base_byte_offset * 8) + obj_desc->common_field.start_field_bit_offset, obj_desc->common_field.bit_length, obj_desc->common_field.access_byte_width); break; - } + default: + break; + } break; @@ -498,7 +498,7 @@ break; - case ACPI_DESC_TYPE_INTERNAL: + case ACPI_DESC_TYPE_OPERAND: obj_type = obj_desc->common.type; @@ -507,8 +507,8 @@ bytes_to_dump = 32; } else { - acpi_os_printf ("(Ptr to ACPI Object type %2.2X [%s])\n", - obj_type, acpi_ut_get_type_name (obj_type)); + acpi_os_printf ("(Ptr to ACPI Object type %s, %X)\n", + acpi_ut_get_type_name (obj_type), obj_type); bytes_to_dump = sizeof (acpi_operand_object); } break; @@ -525,7 +525,7 @@ /* If value is NOT an internal object, we are done */ - if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_INTERNAL) { + if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { goto cleanup; } @@ -534,11 +534,11 @@ */ switch (obj_type) { case ACPI_TYPE_STRING: - obj_desc = (acpi_operand_object *) obj_desc->string.pointer; + obj_desc = (void *) obj_desc->string.pointer; break; case ACPI_TYPE_BUFFER: - obj_desc = (acpi_operand_object *) obj_desc->buffer.pointer; + obj_desc = (void *) obj_desc->buffer.pointer; break; case ACPI_TYPE_BUFFER_FIELD: @@ -546,26 +546,26 @@ break; case ACPI_TYPE_PACKAGE: - obj_desc = (acpi_operand_object *) obj_desc->package.elements; + obj_desc = (void *) obj_desc->package.elements; break; case ACPI_TYPE_METHOD: - obj_desc = (acpi_operand_object *) obj_desc->method.aml_start; + obj_desc = (void *) obj_desc->method.aml_start; break; case INTERNAL_TYPE_REGION_FIELD: - obj_desc = (acpi_operand_object *) obj_desc->field.region_obj; + obj_desc = (void *) obj_desc->field.region_obj; break; case INTERNAL_TYPE_BANK_FIELD: - obj_desc = (acpi_operand_object *) obj_desc->bank_field.region_obj; + obj_desc = (void *) obj_desc->bank_field.region_obj; break; case INTERNAL_TYPE_INDEX_FIELD: - obj_desc = (acpi_operand_object *) obj_desc->index_field.index_obj; + obj_desc = (void *) obj_desc->index_field.index_obj; break; - default: + default: goto cleanup; } @@ -613,8 +613,9 @@ info.display_type = display_type; - acpi_ns_walk_namespace (type, start_handle, max_depth, ACPI_NS_WALK_NO_UNLOCK, acpi_ns_dump_one_object, - (void *) &info, NULL); + (void) acpi_ns_walk_namespace (type, start_handle, max_depth, + ACPI_NS_WALK_NO_UNLOCK, acpi_ns_dump_one_object, + (void *) &info, NULL); } @@ -655,7 +656,7 @@ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " ")); } - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %x\n", + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", info.hardware_id, ACPI_HIDWORD (info.address), ACPI_LODWORD (info.address), info.current_status)); @@ -679,6 +680,7 @@ acpi_ns_dump_root_devices (void) { acpi_handle sys_bus_handle; + acpi_status status; ACPI_FUNCTION_NAME ("Ns_dump_root_devices"); @@ -690,11 +692,16 @@ return; } - acpi_get_handle (0, ACPI_NS_SYSTEM_BUS, &sys_bus_handle); + status = acpi_get_handle (0, ACPI_NS_SYSTEM_BUS, &sys_bus_handle); + if (ACPI_FAILURE (status)) { + return; + } ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Display of all devices in the namespace:\n")); - acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, sys_bus_handle, ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, - acpi_ns_dump_one_device, NULL, NULL); + + status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, sys_bus_handle, + ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, + acpi_ns_dump_one_device, NULL, NULL); } #endif @@ -772,7 +779,7 @@ info.owner_id = ACPI_UINT32_MAX; info.display_type = ACPI_DISPLAY_SUMMARY; - acpi_ns_dump_one_object (handle, 1, &info, NULL); + (void) acpi_ns_dump_one_object (handle, 1, &info, NULL); } #endif diff -Nru a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c --- a/drivers/acpi/namespace/nseval.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/namespace/nseval.c Sun Jun 2 18:44:57 2002 @@ -2,7 +2,7 @@ * * Module Name: nseval - Object evaluation interfaces -- includes control * method lookup and execution. - * $Revision: 112 $ + * $Revision: 114 $ * ******************************************************************************/ @@ -26,7 +26,6 @@ #include "acpi.h" -#include "amlcode.h" #include "acparser.h" #include "acinterp.h" #include "acnamesp.h" @@ -332,12 +331,9 @@ *return_object = local_return_object; } + /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ - /* Map AE_RETURN_VALUE to AE_OK, we are done with it */ - - if (status == AE_CTRL_RETURN_VALUE) { - status = AE_OK; - } + status = AE_OK; } /* @@ -393,7 +389,7 @@ ACPI_DUMP_PATHNAME (method_node, "Ns_execute_control_method: Executing", ACPI_LV_INFO, _COMPONENT); - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %x\n", + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n", obj_desc->method.aml_start + 1, obj_desc->method.aml_length - 1)); /* @@ -444,7 +440,7 @@ acpi_operand_object **return_obj_desc) { acpi_status status = AE_OK; - acpi_operand_object *obj_desc; + acpi_namespace_node *resolved_node = node; ACPI_FUNCTION_TRACE ("Ns_get_object_value"); @@ -455,7 +451,6 @@ * Node may be a field that must be read, etc.) -- we can't just grab * the object out of the node. */ - obj_desc = (acpi_operand_object *) node; /* * Use Resolve_node_to_value() to get the associated value. This call @@ -482,17 +477,17 @@ status = acpi_ex_enter_interpreter (); if (ACPI_SUCCESS (status)) { - status = acpi_ex_resolve_node_to_value ((acpi_namespace_node **) &obj_desc, NULL); + status = acpi_ex_resolve_node_to_value (&resolved_node, NULL); /* * If Acpi_ex_resolve_node_to_value() succeeded, the return value was - * placed in Obj_desc. + * placed in Resolved_node. */ acpi_ex_exit_interpreter (); if (ACPI_SUCCESS (status)) { status = AE_CTRL_RETURN_VALUE; - *return_obj_desc = obj_desc; - ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning obj %p\n", *return_obj_desc)); + *return_obj_desc = ACPI_CAST_PTR (acpi_operand_object, resolved_node); + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning obj %p\n", resolved_node)); } } diff -Nru a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c --- a/drivers/acpi/namespace/nsinit.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/namespace/nsinit.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: nsinit - namespace initialization - * $Revision: 43 $ + * $Revision: 47 $ * *****************************************************************************/ @@ -71,19 +71,20 @@ ACPI_UINT32_MAX, acpi_ns_init_one_object, &info, NULL); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed! %x\n", status)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed! %s\n", + acpi_format_exception (status))); } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, - "\n Initialized %d/%d Regions %d/%d Fields %d/%d Buffers %d/%d Packages (%d nodes)\n", + "\nInitialized %hd/%hd Regions %hd/%hd Fields %hd/%hd Buffers %hd/%hd Packages (%hd nodes)\n", info.op_region_init, info.op_region_count, info.field_init, info.field_count, info.buffer_init, info.buffer_count, info.package_init, info.package_count, info.object_count)); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "%d Control Methods found\n", info.method_count)); + "%hd Control Methods found\n", info.method_count)); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "%d Op Regions found\n", info.op_region_count)); + "%hd Op Regions found\n", info.op_region_count)); return_ACPI_STATUS (AE_OK); } @@ -130,11 +131,12 @@ ACPI_UINT32_MAX, FALSE, acpi_ns_init_one_device, &info, NULL); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed! %x\n", status)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed! %s\n", + acpi_format_exception (status))); } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, - "\n%d Devices found containing: %d _STA, %d _INI methods\n", + "\n%hd Devices found containing: %hd _STA, %hd _INI methods\n", info.device_count, info.num_STA, info.num_INI)); return_ACPI_STATUS (status); @@ -259,13 +261,17 @@ info->package_init++; status = acpi_ds_get_package_arguments (obj_desc); break; + + default: + /* No other types can get here */ + break; } if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n")); ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not execute arguments for [%4.4s] (%s), %s\n", - (char *) &node->name, acpi_ut_get_type_name (type), acpi_format_exception (status))); + node->name.ascii, acpi_ut_get_type_name (type), acpi_format_exception (status))); } if (!(acpi_dbg_level & ACPI_LV_INIT)) { @@ -357,30 +363,36 @@ */ ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (obj_handle, "_INI [Method]")); status = acpi_ns_evaluate_relative (obj_handle, "_INI", NULL, NULL); - if (AE_NOT_FOUND == status) { - /* No _INI means device requires no initialization */ + if (ACPI_FAILURE (status)) { + /* No _INI (AE_NOT_FOUND) means device requires no initialization */ - status = AE_OK; - } + if (status != AE_NOT_FOUND) { + /* Ignore error and move on to next device */ - else if (ACPI_FAILURE (status)) { - /* Ignore error and move on to next device */ + #ifdef ACPI_DEBUG + NATIVE_CHAR *scope_name = acpi_ns_get_external_pathname (obj_handle); -#ifdef ACPI_DEBUG - NATIVE_CHAR *scope_name = acpi_ns_get_external_pathname (obj_handle); + ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n", + scope_name, acpi_format_exception (status))); - ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n", - scope_name, acpi_format_exception (status))); + ACPI_MEM_FREE (scope_name); + #endif + } - ACPI_MEM_FREE (scope_name); -#endif + status = AE_OK; } - else { /* Count of successful INIs */ info->num_INI++; } - return_ACPI_STATUS (AE_OK); + if (acpi_gbl_init_handler) { + /* External initialization handler is present, call it */ + + status = acpi_gbl_init_handler (obj_handle, ACPI_INIT_DEVICE_INI); + } + + + return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c --- a/drivers/acpi/namespace/nsload.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/namespace/nsload.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: nsload - namespace loading/expanding/contracting procedures - * $Revision: 53 $ + * $Revision: 55 $ * *****************************************************************************/ @@ -25,12 +25,10 @@ #include "acpi.h" -#include "acinterp.h" #include "acnamesp.h" #include "amlcode.h" #include "acparser.h" #include "acdispat.h" -#include "acdebug.h" #define _COMPONENT ACPI_NAMESPACE @@ -78,8 +76,8 @@ /* Ignore exceptions from these */ - acpi_ns_load_table_by_type (ACPI_TABLE_SSDT); - acpi_ns_load_table_by_type (ACPI_TABLE_PSDT); + (void) acpi_ns_load_table_by_type (ACPI_TABLE_SSDT); + (void) acpi_ns_load_table_by_type (ACPI_TABLE_PSDT); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "ACPI Namespace successfully loaded at root %p\n", @@ -122,7 +120,7 @@ return_ACPI_STATUS (AE_NO_MEMORY); } - ((acpi_parse2_object *) parse_root)->name = ACPI_ROOT_NAME; + parse_root->named.name = ACPI_ROOT_NAME; /* Create and initialize a new walk state */ @@ -497,7 +495,10 @@ acpi_ns_delete_children (child_handle); child_handle = parent_handle; - acpi_get_parent (parent_handle, &parent_handle); + status = acpi_get_parent (parent_handle, &parent_handle); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } } diff -Nru a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c --- a/drivers/acpi/namespace/nsnames.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/namespace/nsnames.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: nsnames - Name manipulation and search - * $Revision: 74 $ + * $Revision: 77 $ * ******************************************************************************/ @@ -26,7 +26,6 @@ #include "acpi.h" #include "amlcode.h" -#include "acinterp.h" #include "acnamesp.h" @@ -55,7 +54,7 @@ ACPI_SIZE size, NATIVE_CHAR *name_buffer) { - u32 index; + ACPI_SIZE index; acpi_namespace_node *parent_node; @@ -97,7 +96,7 @@ if (index != 0) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not construct pathname; index=%X, size=%X, Path=%s\n", - index, size, &name_buffer[size])); + (u32) index, (u32) size, &name_buffer[size])); } return; @@ -236,7 +235,7 @@ acpi_ns_build_external_path (node, required_size, buffer->pointer); - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s [%X] \n", (char *) buffer->pointer, required_size)); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s [%X] \n", (char *) buffer->pointer, (u32) required_size)); return_ACPI_STATUS (AE_OK); } diff -Nru a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c --- a/drivers/acpi/namespace/nsobject.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/namespace/nsobject.c Sun Jun 2 18:44:57 2002 @@ -2,7 +2,7 @@ * * Module Name: nsobject - Utilities for objects attached to namespace * table entries - * $Revision: 80 $ + * $Revision: 82 $ * ******************************************************************************/ @@ -26,10 +26,7 @@ #include "acpi.h" -#include "amlcode.h" #include "acnamesp.h" -#include "acinterp.h" -#include "actables.h" #define _COMPONENT ACPI_NAMESPACE @@ -141,13 +138,7 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n", - obj_desc, node, (char *) &node->name)); - - /* - * Must increment the new value's reference count - * (if it is an internal object) - */ - acpi_ut_add_reference (obj_desc); + obj_desc, node, node->name.ascii)); /* Detach an existing attached object if present */ @@ -155,19 +146,26 @@ acpi_ns_detach_object (node); } + if (obj_desc) { + /* + * Must increment the new value's reference count + * (if it is an internal object) + */ + acpi_ut_add_reference (obj_desc); - /* - * Handle objects with multiple descriptors - walk - * to the end of the descriptor list - */ - last_obj_desc = obj_desc; - while (last_obj_desc->common.next_object) { - last_obj_desc = last_obj_desc->common.next_object; - } + /* + * Handle objects with multiple descriptors - walk + * to the end of the descriptor list + */ + last_obj_desc = obj_desc; + while (last_obj_desc->common.next_object) { + last_obj_desc = last_obj_desc->common.next_object; + } - /* Install the object at the front of the object list */ + /* Install the object at the front of the object list */ - last_obj_desc->common.next_object = node->object; + last_obj_desc->common.next_object = node->object; + } node->type = (u8) object_type; node->object = obj_desc; @@ -209,7 +207,7 @@ /* Clear the entry in all cases */ node->object = NULL; - if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_INTERNAL) { + if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_OPERAND) { node->object = obj_desc->common.next_object; if (node->object && (node->object->common.type != INTERNAL_TYPE_DATA)) { @@ -222,7 +220,7 @@ node->type = ACPI_TYPE_ANY; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n", - node, (char *) &node->name, obj_desc)); + node, node->name.ascii, obj_desc)); /* Remove one reference on the object (and all subobjects) */ @@ -255,8 +253,8 @@ } if (!node->object || - ((ACPI_GET_DESCRIPTOR_TYPE (node->object) != ACPI_DESC_TYPE_INTERNAL) && - (ACPI_GET_DESCRIPTOR_TYPE (node->object) != ACPI_DESC_TYPE_NAMED)) || + ((ACPI_GET_DESCRIPTOR_TYPE (node->object) != ACPI_DESC_TYPE_OPERAND) && + (ACPI_GET_DESCRIPTOR_TYPE (node->object) != ACPI_DESC_TYPE_NAMED)) || (node->object->common.type == INTERNAL_TYPE_DATA)) { return_PTR (NULL); } diff -Nru a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c --- a/drivers/acpi/namespace/nssearch.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/namespace/nssearch.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: nssearch - Namespace search - * $Revision: 84 $ + * $Revision: 85 $ * ******************************************************************************/ @@ -25,8 +25,6 @@ #include "acpi.h" -#include "amlcode.h" -#include "acinterp.h" #include "acnamesp.h" diff -Nru a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c --- a/drivers/acpi/namespace/nsutils.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/namespace/nsutils.c Sun Jun 2 18:44:57 2002 @@ -2,7 +2,7 @@ * * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing * parents and siblings and Scope manipulation - * $Revision: 105 $ + * $Revision: 109 $ * *****************************************************************************/ @@ -27,7 +27,6 @@ #include "acpi.h" #include "acnamesp.h" -#include "acinterp.h" #include "amlcode.h" #include "actables.h" @@ -146,7 +145,7 @@ * ******************************************************************************/ -acpi_status +void acpi_ns_get_internal_name_length ( acpi_namestring_info *info) { @@ -204,8 +203,6 @@ 4 + info->num_carats; info->next_external_char = next_external_char; - - return (AE_OK); } @@ -230,7 +227,7 @@ NATIVE_CHAR *internal_name = info->internal_name; NATIVE_CHAR *external_name = info->next_external_char; NATIVE_CHAR *result = NULL; - u32 i; + NATIVE_UINT_MIN32 i; ACPI_FUNCTION_TRACE ("Ns_build_internal_name"); @@ -293,7 +290,7 @@ else { /* Convert the character to uppercase and save it */ - result[i] = (char) ACPI_TOUPPER (*external_name); + result[i] = (char) ACPI_TOUPPER ((int) *external_name); external_name++; } } @@ -410,12 +407,12 @@ u32 *converted_name_length, char **converted_name) { - u32 prefix_length = 0; - u32 names_index = 0; - u32 num_segments = 0; - u32 i = 0; - u32 j = 0; - u32 required_length; + NATIVE_UINT_MIN32 prefix_length = 0; + NATIVE_UINT_MIN32 names_index = 0; + NATIVE_UINT_MIN32 num_segments = 0; + NATIVE_UINT_MIN32 i = 0; + NATIVE_UINT_MIN32 j = 0; + NATIVE_UINT_MIN32 required_length; ACPI_FUNCTION_TRACE ("Ns_externalize_name"); @@ -447,6 +444,9 @@ } break; + + default: + break; } /* @@ -534,7 +534,7 @@ } if (converted_name_length) { - *converted_name_length = required_length; + *converted_name_length = (u32) required_length; } return_ACPI_STATUS (AE_OK); @@ -818,16 +818,16 @@ parent_node = acpi_ns_get_parent_node (child_node); if (parent_node) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Parent of %p [%4.4s] is %p [%4.4s]\n", - child_node, (char *) &child_node->name, - parent_node, (char *) &parent_node->name)); + child_node, child_node->name.ascii, + parent_node, parent_node->name.ascii)); if (parent_node->name.integer) { - return_VALUE (parent_node->name.integer); + return_VALUE ((acpi_name) parent_node->name.integer); } } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "unable to find parent of %p (%4.4s)\n", - child_node, (char *) &child_node->name)); + child_node, child_node->name.ascii)); } return_VALUE (ACPI_UNKNOWN_NAME); diff -Nru a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c --- a/drivers/acpi/namespace/nswalk.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/namespace/nswalk.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: nswalk - Functions for walking the ACPI namespace - * $Revision: 32 $ + * $Revision: 33 $ * *****************************************************************************/ @@ -25,7 +25,6 @@ #include "acpi.h" -#include "acinterp.h" #include "acnamesp.h" diff -Nru a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c --- a/drivers/acpi/namespace/nsxfname.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/namespace/nsxfname.c Sun Jun 2 18:44:56 2002 @@ -2,7 +2,7 @@ * * Module Name: nsxfname - Public interfaces to the ACPI subsystem * ACPI Namespace oriented interfaces - * $Revision: 90 $ + * $Revision: 91 $ * *****************************************************************************/ @@ -26,12 +26,7 @@ #include "acpi.h" -#include "acinterp.h" #include "acnamesp.h" -#include "amlcode.h" -#include "acparser.h" -#include "acdispat.h" -#include "acevents.h" #define _COMPONENT ACPI_NAMESPACE @@ -185,7 +180,7 @@ /* Just copy the ACPI name from the Node and zero terminate it */ - ACPI_STRNCPY (buffer->pointer, (NATIVE_CHAR *) &node->name, + ACPI_STRNCPY (buffer->pointer, node->name.ascii, ACPI_NAME_SIZE); ((NATIVE_CHAR *) buffer->pointer) [ACPI_NAME_SIZE] = 0; status = AE_OK; diff -Nru a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c --- a/drivers/acpi/namespace/nsxfobj.c Sun Jun 2 18:44:55 2002 +++ b/drivers/acpi/namespace/nsxfobj.c Sun Jun 2 18:44:55 2002 @@ -2,7 +2,7 @@ * * Module Name: nsxfobj - Public interfaces to the ACPI subsystem * ACPI Object oriented interfaces - * $Revision: 108 $ + * $Revision: 112 $ * ******************************************************************************/ @@ -26,9 +26,7 @@ #include "acpi.h" -#include "acinterp.h" #include "acnamesp.h" -#include "acdispat.h" #define _COMPONENT ACPI_NAMESPACE @@ -37,6 +35,99 @@ /******************************************************************************* * + * FUNCTION: Acpi_evaluate_object_typed + * + * PARAMETERS: Handle - Object handle (optional) + * *Pathname - Object pathname (optional) + * **External_params - List of parameters to pass to method, + * terminated by NULL. May be NULL + * if no parameters are being passed. + * *Return_buffer - Where to put method's return value (if + * any). If NULL, no value is returned. + * Return_type - Expected type of return object + * + * RETURN: Status + * + * DESCRIPTION: Find and evaluate the given object, passing the given + * parameters if necessary. One of "Handle" or "Pathname" must + * be valid (non-null) + * + ******************************************************************************/ + +acpi_status +acpi_evaluate_object_typed ( + acpi_handle handle, + acpi_string pathname, + acpi_object_list *external_params, + acpi_buffer *return_buffer, + acpi_object_type return_type) +{ + acpi_status status; + u8 must_free = FALSE; + + + ACPI_FUNCTION_TRACE ("Acpi_evaluate_object_typed"); + + + /* Return buffer must be valid */ + + if (!return_buffer) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (return_buffer->length == ACPI_ALLOCATE_BUFFER) { + must_free = TRUE; + } + + /* Evaluate the object */ + + status = acpi_evaluate_object (handle, pathname, external_params, return_buffer); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Type ANY means "don't care" */ + + if (return_type == ACPI_TYPE_ANY) { + return_ACPI_STATUS (AE_OK); + } + + if (return_buffer->length == 0) { + /* Error because caller specifically asked for a return value */ + + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "No return value\n")); + + return_ACPI_STATUS (AE_NULL_OBJECT); + } + + /* Examine the object type returned from Evaluate_object */ + + if (((acpi_object *) return_buffer->pointer)->type == return_type) { + return_ACPI_STATUS (AE_OK); + } + + /* Return object type does not match requested type */ + + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Incorrect return type [%s] requested [%s]\n", + acpi_ut_get_type_name (((acpi_object *) return_buffer->pointer)->type), + acpi_ut_get_type_name (return_type))); + + if (must_free) { + /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ + + acpi_os_free (return_buffer->pointer); + return_buffer->pointer = NULL; + } + + return_buffer->length = 0; + return_ACPI_STATUS (AE_TYPE); +} + + +/******************************************************************************* + * * FUNCTION: Acpi_evaluate_object * * PARAMETERS: Handle - Object handle (optional) @@ -82,7 +173,7 @@ * Allocate a new parameter block for the internal objects * Add 1 to count to allow for null terminated internal list */ - internal_params = ACPI_MEM_CALLOCATE ((external_params->count + 1) * + internal_params = ACPI_MEM_CALLOCATE (((ACPI_SIZE) external_params->count + 1) * sizeof (void *)); if (!internal_params) { return_ACPI_STATUS (AE_NO_MEMORY); @@ -198,7 +289,7 @@ */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Needed buffer size %X, %s\n", - buffer_space_needed, acpi_format_exception (status))); + (u32) buffer_space_needed, acpi_format_exception (status))); } else { /* @@ -602,8 +693,8 @@ } } - info->user_function (obj_handle, nesting_level, info->context, return_value); - return (AE_OK); + status = info->user_function (obj_handle, nesting_level, info->context, return_value); + return (status); } diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/osl.c Sun Jun 2 18:44:58 2002 @@ -0,0 +1,910 @@ +/* + * acpi_osl.c - OS-dependent functions ($Revision: 78 $) + * + * Copyright (C) 2000 Andrew Henroid + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "acpi.h" + +#ifdef CONFIG_ACPI_EFI +#include +u64 efi_mem_attributes (u64 phys_addr); +#endif + +#ifdef _IA64 +#include +#include +#endif + + +#define _COMPONENT ACPI_OS_SERVICES +ACPI_MODULE_NAME ("osl") + +#define PREFIX "ACPI: " + +typedef struct +{ + OSD_EXECUTION_CALLBACK function; + void *context; +} ACPI_OS_DPC; + + +#ifdef ENABLE_DEBUGGER +#include +/* stuff for debugger support */ +int acpi_in_debugger = 0; +extern NATIVE_CHAR line_buf[80]; +#endif /*ENABLE_DEBUGGER*/ + +static int acpi_irq_irq = 0; +static OSD_HANDLER acpi_irq_handler = NULL; +static void *acpi_irq_context = NULL; + + +acpi_status +acpi_os_initialize(void) +{ + /* + * Initialize PCI configuration space access, as we'll need to access + * it while walking the namespace (bus 0 and root bridges w/ _BBNs). + */ +#ifdef CONFIG_ACPI_PCI + if (!pci_config_read || !pci_config_write) { + printk(KERN_ERR PREFIX "Access to PCI configuration space unavailable\n"); + return AE_NULL_ENTRY; + } +#endif + + return AE_OK; +} + +acpi_status +acpi_os_terminate(void) +{ + if (acpi_irq_handler) { + acpi_os_remove_interrupt_handler(acpi_irq_irq, + acpi_irq_handler); + } + + return AE_OK; +} + +void +acpi_os_printf(const NATIVE_CHAR *fmt,...) +{ + va_list args; + va_start(args, fmt); + acpi_os_vprintf(fmt, args); + va_end(args); +} + +void +acpi_os_vprintf(const NATIVE_CHAR *fmt, va_list args) +{ + static char buffer[512]; + + vsprintf(buffer, fmt, args); + +#ifdef ENABLE_DEBUGGER + if (acpi_in_debugger) { + kdb_printf("%s", buffer); + } else { + printk("%s", buffer); + } +#else + printk("%s", buffer); +#endif +} + +void * +acpi_os_allocate(ACPI_SIZE size) +{ + return kmalloc(size, GFP_KERNEL); +} + +void * +acpi_os_callocate(ACPI_SIZE size) +{ + void *ptr = acpi_os_allocate(size); + if (ptr) + memset(ptr, 0, size); + + return ptr; +} + +void +acpi_os_free(void *ptr) +{ + kfree(ptr); +} + +acpi_status +acpi_os_get_root_pointer(u32 flags, ACPI_POINTER *addr) +{ +#ifdef CONFIG_ACPI_EFI + addr->pointer_type = ACPI_PHYSICAL_POINTER; + if (efi.acpi20) + addr->pointer.physical = (ACPI_PHYSICAL_ADDRESS) virt_to_phys(efi.acpi20); + else if (efi.acpi) + addr->pointer.physical = (ACPI_PHYSICAL_ADDRESS) virt_to_phys(efi.acpi); + else { + printk(KERN_ERR PREFIX "System description tables not found\n"); + return AE_NOT_FOUND; + } +#else + if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) { + printk(KERN_ERR PREFIX "System description tables not found\n"); + return AE_NOT_FOUND; + } +#endif /*CONFIG_ACPI_EFI*/ + + return AE_OK; +} + +acpi_status +acpi_os_map_memory(ACPI_PHYSICAL_ADDRESS phys, ACPI_SIZE size, void **virt) +{ +#ifdef CONFIG_ACPI_EFI + if (EFI_MEMORY_UC & efi_mem_attributes(phys)) { + *virt = ioremap(phys, size); + } else { + *virt = phys_to_virt(phys); + } +#else + if (phys > ULONG_MAX) { + printk(KERN_ERR PREFIX "Cannot map memory that high\n"); + return AE_BAD_PARAMETER; + } + /* + * ioremap checks to ensure this is in reserved space + */ + *virt = ioremap((unsigned long) phys, size); +#endif + + if (!*virt) + return AE_NO_MEMORY; + + return AE_OK; +} + +void +acpi_os_unmap_memory(void *virt, ACPI_SIZE size) +{ + iounmap(virt); +} + +acpi_status +acpi_os_get_physical_address(void *virt, ACPI_PHYSICAL_ADDRESS *phys) +{ + if(!phys || !virt) + return AE_BAD_PARAMETER; + + *phys = virt_to_phys(virt); + + return AE_OK; +} + +acpi_status +acpi_os_table_override (acpi_table_header *existing_table, acpi_table_header **new_table) +{ + if (!existing_table || !new_table) + return AE_BAD_PARAMETER; + + *new_table = NULL; + return AE_OK; +} + +static void +acpi_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + (*acpi_irq_handler)(acpi_irq_context); +} + +acpi_status +acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context) +{ +#ifdef _IA64 + irq = isa_irq_to_vector(irq); +#endif /*_IA64*/ + acpi_irq_irq = irq; + acpi_irq_handler = handler; + acpi_irq_context = context; + if (request_irq(irq, acpi_irq, SA_SHIRQ, "acpi", acpi_irq)) { + printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); + return AE_NOT_ACQUIRED; + } + + return AE_OK; +} + +acpi_status +acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler) +{ + if (acpi_irq_handler) { +#ifdef _IA64 + irq = isa_irq_to_vector(irq); +#endif /*_IA64*/ + free_irq(irq, acpi_irq); + acpi_irq_handler = NULL; + } + + return AE_OK; +} + +/* + * Running in interpreter thread context, safe to sleep + */ + +void +acpi_os_sleep(u32 sec, u32 ms) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ * sec + (ms * HZ) / 1000); +} + +void +acpi_os_stall(u32 us) +{ + if (us > 10000) { + mdelay(us / 1000); + } + else { + udelay(us); + } +} + +acpi_status +acpi_os_read_port( + ACPI_IO_ADDRESS port, + void *value, + u32 width) +{ + u32 dummy; + + if (!value) + value = &dummy; + + switch (width) + { + case 8: + *(u8*) value = inb(port); + break; + case 16: + *(u16*) value = inw(port); + break; + case 32: + *(u32*) value = inl(port); + break; + default: + BUG(); + } + + return AE_OK; +} + +acpi_status +acpi_os_write_port( + ACPI_IO_ADDRESS port, + acpi_integer value, + u32 width) +{ + switch (width) + { + case 8: + outb(value, port); + break; + case 16: + outw(value, port); + break; + case 32: + outl(value, port); + break; + default: + BUG(); + } + + return AE_OK; +} + +acpi_status +acpi_os_read_memory( + ACPI_PHYSICAL_ADDRESS phys_addr, + void *value, + u32 width) +{ + u32 dummy; + void *virt_addr; + +#ifdef CONFIG_ACPI_EFI + int iomem = 0; + + if (EFI_MEMORY_UC & efi_mem_attributes(phys_addr)) { + iomem = 1; + virt_addr = ioremap(phys_addr, width); + } + else + virt_addr = phys_to_virt(phys_addr); +#else + virt_addr = phys_to_virt(phys_addr); +#endif + if (!value) + value = &dummy; + + switch (width) { + case 8: + *(u8*) value = *(u8*) virt_addr; + break; + case 16: + *(u16*) value = *(u16*) virt_addr; + break; + case 32: + *(u32*) value = *(u32*) virt_addr; + break; + default: + BUG(); + } + +#ifdef CONFIG_ACPI_EFI + if (iomem) + iounmap(virt_addr); +#endif + + return AE_OK; +} + +acpi_status +acpi_os_write_memory( + ACPI_PHYSICAL_ADDRESS phys_addr, + acpi_integer value, + u32 width) +{ + void *virt_addr; + +#ifdef CONFIG_ACPI_EFI + int iomem = 0; + + if (EFI_MEMORY_UC & efi_mem_attributes(phys_addr)) { + iomem = 1; + virt_addr = ioremap(phys_addr,width); + } + else + virt_addr = phys_to_virt(phys_addr); +#else + virt_addr = phys_to_virt(phys_addr); +#endif + + switch (width) { + case 8: + *(u8*) virt_addr = value; + break; + case 16: + *(u16*) virt_addr = value; + break; + case 32: + *(u32*) virt_addr = value; + break; + default: + BUG(); + } + +#ifdef CONFIG_ACPI_EFI + if (iomem) + iounmap(virt_addr); +#endif + + return AE_OK; +} + +#ifdef CONFIG_ACPI_PCI + +acpi_status +acpi_os_read_pci_configuration ( + acpi_pci_id *pci_id, + u32 reg, + void *value, + u32 width) +{ + int result = 0; + if (!value) + return AE_BAD_PARAMETER; + + switch (width) + { + case 8: + result = pci_config_read(pci_id->segment, pci_id->bus, + pci_id->device, pci_id->function, reg, 1, value); + break; + case 16: + result = pci_config_read(pci_id->segment, pci_id->bus, + pci_id->device, pci_id->function, reg, 2, value); + break; + case 32: + result = pci_config_read(pci_id->segment, pci_id->bus, + pci_id->device, pci_id->function, reg, 4, value); + break; + default: + BUG(); + } + + return (result ? AE_ERROR : AE_OK); +} + +acpi_status +acpi_os_write_pci_configuration ( + acpi_pci_id *pci_id, + u32 reg, + acpi_integer value, + u32 width) +{ + int result = 0; + + switch (width) + { + case 8: + result = pci_config_write(pci_id->segment, pci_id->bus, + pci_id->device, pci_id->function, reg, 1, value); + break; + case 16: + result = pci_config_write(pci_id->segment, pci_id->bus, + pci_id->device, pci_id->function, reg, 2, value); + break; + case 32: + result = pci_config_write(pci_id->segment, pci_id->bus, + pci_id->device, pci_id->function, reg, 4, value); + break; + default: + BUG(); + } + + return (result ? AE_ERROR : AE_OK); +} + +#else /*!CONFIG_ACPI_PCI*/ + +acpi_status +acpi_os_write_pci_configuration ( + acpi_pci_id *pci_id, + u32 reg, + acpi_integer value, + u32 width) +{ + return (AE_SUPPORT); +} + +acpi_status +acpi_os_read_pci_configuration ( + acpi_pci_id *pci_id, + u32 reg, + void *value, + u32 width) +{ + return (AE_SUPPORT); +} + +#endif /*CONFIG_ACPI_PCI*/ + +acpi_status +acpi_os_load_module ( + char *module_name) +{ + ACPI_FUNCTION_TRACE ("os_load_module"); + + if (!module_name) + return_ACPI_STATUS (AE_BAD_PARAMETER); + + if (request_module(module_name) < 0) { + ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to load module [%s].\n", module_name)); + return_ACPI_STATUS (AE_ERROR); + } + + return_ACPI_STATUS (AE_OK); +} + +acpi_status +acpi_os_unload_module ( + char *module_name) +{ + if (!module_name) + return AE_BAD_PARAMETER; + + /* TODO: How on Linux? */ + /* this is done automatically for all modules with + use_count = 0, I think. see: MOD_INC_USE_COUNT -ASG */ + + return AE_OK; +} + + +/* + * See acpi_os_queue_for_execution() + */ +static int +acpi_os_queue_exec ( + void *context) +{ + ACPI_OS_DPC *dpc = (ACPI_OS_DPC*)context; + + ACPI_FUNCTION_TRACE ("os_queue_exec"); + + daemonize(); + strcpy(current->comm, "kacpidpc"); + + if (!dpc || !dpc->function) + return_ACPI_STATUS (AE_BAD_PARAMETER); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Executing function [%p(%p)].\n", dpc->function, dpc->context)); + + dpc->function(dpc->context); + + kfree(dpc); + + return_ACPI_STATUS (AE_OK); +} + +static void +acpi_os_schedule_exec ( + void *context) +{ + ACPI_OS_DPC *dpc = NULL; + int thread_pid = -1; + + ACPI_FUNCTION_TRACE ("os_schedule_exec"); + + dpc = (ACPI_OS_DPC*)context; + if (!dpc) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n")); + return_VOID; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Creating new thread to run function [%p(%p)].\n", dpc->function, dpc->context)); + + thread_pid = kernel_thread(acpi_os_queue_exec, dpc, + (CLONE_FS | CLONE_FILES | SIGCHLD)); + if (thread_pid < 0) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to kernel_thread() failed.\n")); + acpi_os_free(dpc); + } + return_VOID; +} + +acpi_status +acpi_os_queue_for_execution( + u32 priority, + OSD_EXECUTION_CALLBACK function, + void *context) +{ + acpi_status status = AE_OK; + ACPI_OS_DPC *dpc = NULL; + + ACPI_FUNCTION_TRACE ("os_queue_for_execution"); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); + + if (!function) + return_ACPI_STATUS (AE_BAD_PARAMETER); + + /* + * Queue via DPC: + * -------------- + * Note that we have to use two different processes for queuing DPCs: + * Interrupt-Level: Use schedule_task; can't spawn a new thread. + * Kernel-Level: Spawn a new kernel thread, as schedule_task has + * its limitations (e.g. single-threaded model), and + * all other task queues run at interrupt-level. + */ + switch (priority) { + + case OSD_PRIORITY_GPE: + { + static struct tq_struct task; + + /* + * Allocate/initialize DPC structure. Note that this memory will be + * freed by the callee. + */ + dpc = kmalloc(sizeof(ACPI_OS_DPC), GFP_ATOMIC); + if (!dpc) + return_ACPI_STATUS (AE_NO_MEMORY); + + dpc->function = function; + dpc->context = context; + + memset(&task, 0, sizeof(struct tq_struct)); + + task.routine = acpi_os_schedule_exec; + task.data = (void*)dpc; + + if (schedule_task(&task) < 0) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to schedule_task() failed.\n")); + status = AE_ERROR; + } + } + break; + + default: + /* + * Allocate/initialize DPC structure. Note that this memory will be + * freed by the callee. + */ + dpc = kmalloc(sizeof(ACPI_OS_DPC), GFP_KERNEL); + if (!dpc) + return_ACPI_STATUS (AE_NO_MEMORY); + + dpc->function = function; + dpc->context = context; + + acpi_os_schedule_exec(dpc); + break; + } + + return_ACPI_STATUS (status); +} + + +acpi_status +acpi_os_create_semaphore( + u32 max_units, + u32 initial_units, + acpi_handle *handle) +{ + struct semaphore *sem = NULL; + + ACPI_FUNCTION_TRACE ("os_create_semaphore"); + + sem = acpi_os_callocate(sizeof(struct semaphore)); + if (!sem) + return_ACPI_STATUS (AE_NO_MEMORY); + + sema_init(sem, initial_units); + + *handle = (acpi_handle*)sem; + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Creating semaphore[%p|%d].\n", *handle, initial_units)); + + return_ACPI_STATUS (AE_OK); +} + + +/* + * TODO: A better way to delete semaphores? Linux doesn't have a + * 'delete_semaphore()' function -- may result in an invalid + * pointer dereference for non-synchronized consumers. Should + * we at least check for blocked threads and signal/cancel them? + */ + +acpi_status +acpi_os_delete_semaphore( + acpi_handle handle) +{ + struct semaphore *sem = (struct semaphore*) handle; + + ACPI_FUNCTION_TRACE ("os_delete_semaphore"); + + if (!sem) + return_ACPI_STATUS (AE_BAD_PARAMETER); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Deleting semaphore[%p].\n", handle)); + + acpi_os_free(sem); sem = NULL; + + return_ACPI_STATUS (AE_OK); +} + + +/* + * TODO: The kernel doesn't have a 'down_timeout' function -- had to + * improvise. The process is to sleep for one scheduler quantum + * until the semaphore becomes available. Downside is that this + * may result in starvation for timeout-based waits when there's + * lots of semaphore activity. + * + * TODO: Support for units > 1? + */ +acpi_status +acpi_os_wait_semaphore( + acpi_handle handle, + u32 units, + u32 timeout) +{ + acpi_status status = AE_OK; + struct semaphore *sem = (struct semaphore*)handle; + int ret = 0; + + ACPI_FUNCTION_TRACE ("os_wait_semaphore"); + + if (!sem || (units < 1)) + return_ACPI_STATUS (AE_BAD_PARAMETER); + + if (units > 1) + return_ACPI_STATUS (AE_SUPPORT); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); + + switch (timeout) + { + /* + * No Wait: + * -------- + * A zero timeout value indicates that we shouldn't wait - just + * acquire the semaphore if available otherwise return AE_TIME + * (a.k.a. 'would block'). + */ + case 0: + if(down_trylock(sem)) + status = AE_TIME; + break; + + /* + * Wait Indefinitely: + * ------------------ + */ + case WAIT_FOREVER: + ret = down_interruptible(sem); + if (ret < 0) + status = AE_ERROR; + break; + + /* + * Wait w/ Timeout: + * ---------------- + */ + default: + // TODO: A better timeout algorithm? + { + int i = 0; + static const int quantum_ms = 1000/HZ; + + ret = down_trylock(sem); + for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + ret = down_trylock(sem); + } + + if (ret != 0) + status = AE_TIME; + } + break; + } + + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Failed to acquire semaphore[%p|%d|%d]\n", handle, units, timeout)); + } + else { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout)); + } + + return_ACPI_STATUS (status); +} + + +/* + * TODO: Support for units > 1? + */ +acpi_status +acpi_os_signal_semaphore( + acpi_handle handle, + u32 units) +{ + struct semaphore *sem = (struct semaphore *) handle; + + ACPI_FUNCTION_TRACE ("os_signal_semaphore"); + + if (!sem || (units < 1)) + return_ACPI_STATUS (AE_BAD_PARAMETER); + + if (units > 1) + return_ACPI_STATUS (AE_SUPPORT); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Signaling semaphore[%p|%d]\n", handle, units)); + + up(sem); + + return_ACPI_STATUS (AE_OK); +} + +u32 +acpi_os_get_line(NATIVE_CHAR *buffer) +{ + +#ifdef ENABLE_DEBUGGER + if (acpi_in_debugger) { + u32 chars; + + kdb_read(buffer, sizeof(line_buf)); + + /* remove the CR kdb includes */ + chars = strlen(buffer) - 1; + buffer[chars] = '\0'; + } +#endif + + return 0; +} + +/* + * We just have to assume we're dealing with valid memory + */ + +BOOLEAN +acpi_os_readable(void *ptr, u32 len) +{ + return 1; +} + +BOOLEAN +acpi_os_writable(void *ptr, u32 len) +{ + return 1; +} + +u32 +acpi_os_get_thread_id (void) +{ + if (!in_interrupt()) + return current->pid; + + return 0; +} + +acpi_status +acpi_os_signal ( + u32 function, + void *info) +{ + switch (function) + { + case ACPI_SIGNAL_FATAL: + printk(KERN_ERR PREFIX "Fatal opcode executed\n"); + break; + case ACPI_SIGNAL_BREAKPOINT: + { + char *bp_info = (char*) info; + + printk(KERN_ERR "ACPI breakpoint: %s\n", bp_info); + } + default: + break; + } + + return AE_OK; +} + +acpi_status +acpi_os_breakpoint(NATIVE_CHAR *msg) +{ + acpi_os_printf("breakpoint: %s", msg); + + return AE_OK; +} + diff -Nru a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c --- a/drivers/acpi/parser/psargs.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/parser/psargs.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psargs - Parse AML opcode arguments - * $Revision: 58 $ + * $Revision: 61 $ * *****************************************************************************/ @@ -93,6 +93,10 @@ (encoded_length & 0x0F)); parser_state->aml += 3; break; + + default: + /* Can't get here, only 2 bits / 4 cases */ + break; } return_VALUE (length); @@ -148,9 +152,8 @@ acpi_ps_get_next_namestring ( acpi_parse_state *parser_state) { - u8 *start = parser_state->aml; - u8 *end = parser_state->aml; - u32 length; + u8 *start = parser_state->aml; + u8 *end = parser_state->aml; ACPI_FUNCTION_TRACE ("Ps_get_next_namestring"); @@ -177,35 +180,29 @@ end++; break; - case AML_DUAL_NAME_PREFIX: - /* two name segments */ + /* Two name segments */ end += 9; break; - case AML_MULTI_NAME_PREFIX_OP: - /* multiple name segments */ + /* Multiple name segments, 4 chars each */ - length = (u32) ACPI_GET8 (end + 1) * 4; - end += 2 + length; + end += 2 + ((ACPI_SIZE) ACPI_GET8 (end + 1) * 4); break; - default: - /* single name segment */ - /* assert (Acpi_ps_is_lead (GET8 (End))); */ + /* Single name segment */ end += 4; break; } parser_state->aml = (u8*) end; - return_PTR ((NATIVE_CHAR *) start); } @@ -255,7 +252,7 @@ /* Null name case, create a null namepath object */ acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP); - arg->value.name = path; + arg->common.value.name = path; return_VOID; } @@ -271,7 +268,7 @@ } if (op) { - if (op->opcode == AML_METHOD_OP) { + if (op->common.aml_opcode == AML_METHOD_OP) { /* * The name refers to a control method, so this namepath is a * method invocation. We need to 1) Get the number of arguments @@ -279,21 +276,21 @@ * object into a METHODCALL object. */ count = acpi_ps_get_arg (op, 0); - if (count && count->opcode == AML_BYTE_OP) { + if (count && count->common.aml_opcode == AML_BYTE_OP) { name_op = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP); if (name_op) { /* Change arg into a METHOD CALL and attach the name */ acpi_ps_init_op (arg, AML_INT_METHODCALL_OP); - name_op->value.name = path; + name_op->common.value.name = path; /* Point METHODCALL/NAME to the METHOD Node */ - name_op->node = (acpi_namespace_node *) op; + name_op->common.node = (acpi_namespace_node *) op; acpi_ps_append_arg (arg, name_op); - *arg_count = (u32) count->value.integer & + *arg_count = (u32) count->common.value.integer & METHOD_FLAGS_ARG_COUNT; } } @@ -315,7 +312,7 @@ * pathname */ acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP); - arg->value.name = path; + arg->common.value.name = path; return_VOID; @@ -348,65 +345,62 @@ /* Null name case, create a null namepath object */ acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP); - arg->value.name = path; + arg->common.value.name = path; return_VOID; } + /* + * Lookup the name in the internal namespace + */ + scope_info.scope.node = NULL; + node = parser_state->start_node; + if (node) { + scope_info.scope.node = node; + } - if (method_call) { - /* - * Lookup the name in the internal namespace - */ - scope_info.scope.node = NULL; - node = parser_state->start_node; - if (node) { - scope_info.scope.node = node; - } - - /* - * Lookup object. We don't want to add anything new to the namespace - * here, however. So we use MODE_EXECUTE. Allow searching of the - * parent tree, but don't open a new scope -- we just want to lookup the - * object (MUST BE mode EXECUTE to perform upsearch) - */ - status = acpi_ns_lookup (&scope_info, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, - ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, - &node); - if (ACPI_SUCCESS (status)) { - if (node->type == ACPI_TYPE_METHOD) { - method_node = node; - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "method - %p Path=%p\n", - method_node, path)); - - name_op = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP); - if (name_op) { - /* Change arg into a METHOD CALL and attach name to it */ - - acpi_ps_init_op (arg, AML_INT_METHODCALL_OP); - - name_op->value.name = path; - - /* Point METHODCALL/NAME to the METHOD Node */ + /* + * Lookup object. We don't want to add anything new to the namespace + * here, however. So we use MODE_EXECUTE. Allow searching of the + * parent tree, but don't open a new scope -- we just want to lookup the + * object (MUST BE mode EXECUTE to perform upsearch) + */ + status = acpi_ns_lookup (&scope_info, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, + &node); + if (ACPI_SUCCESS (status)) { + if (node->type == ACPI_TYPE_METHOD) { + method_node = node; + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "method - %p Path=%p\n", + method_node, path)); + + name_op = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP); + if (name_op) { + /* Change arg into a METHOD CALL and attach name to it */ + + acpi_ps_init_op (arg, AML_INT_METHODCALL_OP); + + name_op->common.value.name = path; - name_op->node = method_node; - acpi_ps_append_arg (arg, name_op); + /* Point METHODCALL/NAME to the METHOD Node */ - if (!acpi_ns_get_attached_object (method_node)) { - return_VOID; - } + name_op->common.node = method_node; + acpi_ps_append_arg (arg, name_op); - *arg_count = (acpi_ns_get_attached_object (method_node))->method.param_count; + if (!acpi_ns_get_attached_object (method_node)) { + return_VOID; } - return_VOID; + *arg_count = (acpi_ns_get_attached_object (method_node))->method.param_count; } - /* - * Else this is normal named object reference. - * Just init the NAMEPATH object with the pathname. - * (See code below) - */ + return_VOID; } + + /* + * Else this is normal named object reference. + * Just init the NAMEPATH object with the pathname. + * (See code below) + */ } /* @@ -415,7 +409,7 @@ * pathname. */ acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP); - arg->value.name = path; + arg->common.value.name = path; return_VOID; @@ -448,11 +442,10 @@ switch (arg_type) { - case ARGP_BYTEDATA: acpi_ps_init_op (arg, AML_BYTE_OP); - arg->value.integer = (u32) ACPI_GET8 (parser_state->aml); + arg->common.value.integer = (u32) ACPI_GET8 (parser_state->aml); parser_state->aml++; break; @@ -463,7 +456,7 @@ /* Get 2 bytes from the AML stream */ - ACPI_MOVE_UNALIGNED16_TO_32 (&arg->value.integer, parser_state->aml); + ACPI_MOVE_UNALIGNED16_TO_32 (&arg->common.value.integer, parser_state->aml); parser_state->aml += 2; break; @@ -474,7 +467,7 @@ /* Get 4 bytes from the AML stream */ - ACPI_MOVE_UNALIGNED32_TO_32 (&arg->value.integer, parser_state->aml); + ACPI_MOVE_UNALIGNED32_TO_32 (&arg->common.value.integer, parser_state->aml); parser_state->aml += 4; break; @@ -485,7 +478,7 @@ /* Get 8 bytes from the AML stream */ - ACPI_MOVE_UNALIGNED64_TO_64 (&arg->value.integer, parser_state->aml); + ACPI_MOVE_UNALIGNED64_TO_64 (&arg->common.value.integer, parser_state->aml); parser_state->aml += 8; break; @@ -493,7 +486,7 @@ case ARGP_CHARLIST: acpi_ps_init_op (arg, AML_STRING_OP); - arg->value.string = (char *) parser_state->aml; + arg->common.value.string = (char *) parser_state->aml; while (ACPI_GET8 (parser_state->aml) != '\0') { parser_state->aml++; @@ -506,7 +499,12 @@ case ARGP_NAMESTRING: acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP); - arg->value.name = acpi_ps_get_next_namestring (parser_state); + arg->common.value.name = acpi_ps_get_next_namestring (parser_state); + break; + + + default: + ACPI_REPORT_ERROR (("Invalid Arg_type %X\n", arg_type)); break; } @@ -530,8 +528,8 @@ acpi_ps_get_next_field ( acpi_parse_state *parser_state) { - u32 aml_offset = parser_state->aml - - parser_state->aml_start; + u32 aml_offset = ACPI_PTR_DIFF (parser_state->aml, + parser_state->aml_start); acpi_parse_object *field; u16 opcode; u32 name; @@ -543,20 +541,17 @@ /* determine field type */ switch (ACPI_GET8 (parser_state->aml)) { - default: opcode = AML_INT_NAMEDFIELD_OP; break; - case 0x00: opcode = AML_INT_RESERVEDFIELD_OP; parser_state->aml++; break; - case 0x01: opcode = AML_INT_ACCESSFIELD_OP; @@ -568,46 +563,52 @@ /* Allocate a new field op */ field = acpi_ps_alloc_op (opcode); - if (field) { - field->aml_offset = aml_offset; + if (!field) { + return_PTR (NULL); + } - /* Decode the field type */ + field->common.aml_offset = aml_offset; - switch (opcode) { - case AML_INT_NAMEDFIELD_OP: + /* Decode the field type */ - /* Get the 4-character name */ + switch (opcode) { + case AML_INT_NAMEDFIELD_OP: - ACPI_MOVE_UNALIGNED32_TO_32 (&name, parser_state->aml); - acpi_ps_set_name (field, name); - parser_state->aml += 4; + /* Get the 4-character name */ - /* Get the length which is encoded as a package length */ + ACPI_MOVE_UNALIGNED32_TO_32 (&name, parser_state->aml); + acpi_ps_set_name (field, name); + parser_state->aml += 4; - field->value.size = acpi_ps_get_next_package_length (parser_state); - break; + /* Get the length which is encoded as a package length */ + field->common.value.size = acpi_ps_get_next_package_length (parser_state); + break; - case AML_INT_RESERVEDFIELD_OP: - /* Get the length which is encoded as a package length */ + case AML_INT_RESERVEDFIELD_OP: - field->value.size = acpi_ps_get_next_package_length (parser_state); - break; + /* Get the length which is encoded as a package length */ + field->common.value.size = acpi_ps_get_next_package_length (parser_state); + break; - case AML_INT_ACCESSFIELD_OP: - /* - * Get Access_type and Access_attrib and merge into the field Op - * Access_type is first operand, Access_attribute is second - */ - field->value.integer32 = (ACPI_GET8 (parser_state->aml) << 8); - parser_state->aml++; - field->value.integer32 |= ACPI_GET8 (parser_state->aml); - parser_state->aml++; - break; - } + case AML_INT_ACCESSFIELD_OP: + + /* + * Get Access_type and Access_attrib and merge into the field Op + * Access_type is first operand, Access_attribute is second + */ + field->common.value.integer32 = (ACPI_GET8 (parser_state->aml) << 8); + parser_state->aml++; + field->common.value.integer32 |= ACPI_GET8 (parser_state->aml); + parser_state->aml++; + break; + + default: + /* Opcode was set in previous switch */ + break; } return_PTR (field); @@ -682,7 +683,7 @@ } if (prev) { - prev->next = field; + prev->common.next = field; } else { @@ -708,8 +709,8 @@ if (arg) { /* fill in bytelist data */ - arg->value.size = (parser_state->pkg_end - parser_state->aml); - ((acpi_parse2_object *) arg)->data = parser_state->aml; + arg->common.value.size = ACPI_PTR_DIFF (parser_state->pkg_end, parser_state->aml); + arg->named.data = parser_state->aml; } /* skip to End of byte data */ @@ -761,6 +762,10 @@ *arg_count = ACPI_VAR_ARGS; } + break; + + default: + ACPI_REPORT_ERROR (("Invalid Arg_type: %X\n", arg_type)); break; } diff -Nru a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c --- a/drivers/acpi/parser/psopcode.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/parser/psopcode.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psopcode - Parser/Interpreter opcode information table - * $Revision: 66 $ + * $Revision: 69 $ * *****************************************************************************/ @@ -45,9 +45,9 @@ #define _UNKNOWN_OPCODE 0x02 /* An example unknown opcode */ #define MAX_EXTENDED_OPCODE 0x88 -#define NUM_EXTENDED_OPCODE MAX_EXTENDED_OPCODE + 1 +#define NUM_EXTENDED_OPCODE (MAX_EXTENDED_OPCODE + 1) #define MAX_INTERNAL_OPCODE -#define NUM_INTERNAL_OPCODE MAX_INTERNAL_OPCODE + 1 +#define NUM_INTERNAL_OPCODE (MAX_INTERNAL_OPCODE + 1) /******************************************************************************* @@ -448,22 +448,22 @@ */ -static const acpi_opcode_info acpi_gbl_aml_op_info[] = +const acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { /*! [Begin] no source code translation */ /* Index Name Parser Args Interpreter Args ObjectType Class Type Flags */ -/* 00 */ ACPI_OP ("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, 0), -/* 01 */ ACPI_OP ("One", ARGP_ONE_OP, ARGI_ONE_OP, INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, 0), +/* 00 */ ACPI_OP ("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), +/* 01 */ ACPI_OP ("One", ARGP_ONE_OP, ARGI_ONE_OP, INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), /* 02 */ ACPI_OP ("Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP, INTERNAL_TYPE_ALIAS, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), /* 03 */ ACPI_OP ("Name", ARGP_NAME_OP, ARGI_NAME_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), -/* 04 */ ACPI_OP ("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, 0), -/* 05 */ ACPI_OP ("WordConst", ARGP_WORD_OP, ARGI_WORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, 0), -/* 06 */ ACPI_OP ("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, 0), -/* 07 */ ACPI_OP ("String", ARGP_STRING_OP, ARGI_STRING_OP, ACPI_TYPE_STRING, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, 0), +/* 04 */ ACPI_OP ("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT), +/* 05 */ ACPI_OP ("WordConst", ARGP_WORD_OP, ARGI_WORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT), +/* 06 */ ACPI_OP ("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT), +/* 07 */ ACPI_OP ("String", ARGP_STRING_OP, ARGI_STRING_OP, ACPI_TYPE_STRING, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT), /* 08 */ ACPI_OP ("Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP, INTERNAL_TYPE_SCOPE, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), -/* 09 */ ACPI_OP ("Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP, ACPI_TYPE_BUFFER, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER), -/* 0A */ ACPI_OP ("Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER), +/* 09 */ ACPI_OP ("Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP, ACPI_TYPE_BUFFER, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER | AML_CONSTANT), +/* 0A */ ACPI_OP ("Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER | AML_CONSTANT), /* 0B */ ACPI_OP ("Method", ARGP_METHOD_OP, ARGI_METHOD_OP, ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED | AML_DEFER), /* 0C */ ACPI_OP ("Local0", ARGP_LOCAL0, ARGI_LOCAL0, INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0), /* 0D */ ACPI_OP ("Local1", ARGP_LOCAL1, ARGI_LOCAL1, INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LOCAL_VARIABLE, 0), @@ -482,39 +482,39 @@ /* 1A */ ACPI_OP ("Arg6", ARGP_ARG6, ARGI_ARG6, INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_METHOD_ARGUMENT, 0), /* 1B */ ACPI_OP ("Store", ARGP_STORE_OP, ARGI_STORE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), /* 1C */ ACPI_OP ("RefOf", ARGP_REF_OF_OP, ARGI_REF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), -/* 1D */ ACPI_OP ("Add", ARGP_ADD_OP, ARGI_ADD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH), -/* 1E */ ACPI_OP ("Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R), -/* 1F */ ACPI_OP ("Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH), -/* 20 */ ACPI_OP ("Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), -/* 21 */ ACPI_OP ("Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), -/* 22 */ ACPI_OP ("Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH), -/* 23 */ ACPI_OP ("Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_2T_1R, AML_FLAGS_EXEC_2A_2T_1R), -/* 24 */ ACPI_OP ("ShiftLeft", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH), -/* 25 */ ACPI_OP ("ShiftRight", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH), -/* 26 */ ACPI_OP ("And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH), -/* 27 */ ACPI_OP ("NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH), -/* 28 */ ACPI_OP ("Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH), -/* 29 */ ACPI_OP ("NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH), -/* 2A */ ACPI_OP ("XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH), -/* 2B */ ACPI_OP ("Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), -/* 2C */ ACPI_OP ("FindSetLeftBit", ARGP_FIND_SET_LEFT_BIT_OP, ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), -/* 2D */ ACPI_OP ("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP,ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), +/* 1D */ ACPI_OP ("Add", ARGP_ADD_OP, ARGI_ADD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 1E */ ACPI_OP ("Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), +/* 1F */ ACPI_OP ("Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 20 */ ACPI_OP ("Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), +/* 21 */ ACPI_OP ("Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), +/* 22 */ ACPI_OP ("Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 23 */ ACPI_OP ("Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_2T_1R, AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT), +/* 24 */ ACPI_OP ("ShiftLeft", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 25 */ ACPI_OP ("ShiftRight", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 26 */ ACPI_OP ("And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 27 */ ACPI_OP ("NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 28 */ ACPI_OP ("Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 29 */ ACPI_OP ("NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 2A */ ACPI_OP ("XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), +/* 2B */ ACPI_OP ("Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 2C */ ACPI_OP ("FindSetLeftBit", ARGP_FIND_SET_LEFT_BIT_OP, ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 2D */ ACPI_OP ("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP,ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 2E */ ACPI_OP ("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), /* 2F */ ACPI_OP ("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R), /* 30 */ ACPI_OP ("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), -/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R), -/* 32 */ ACPI_OP ("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R), +/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), +/* 32 */ ACPI_OP ("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT), /* 33 */ ACPI_OP ("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,ARGI_CREATE_DWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), /* 34 */ ACPI_OP ("CreateWordField", ARGP_CREATE_WORD_FIELD_OP, ARGI_CREATE_WORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), /* 35 */ ACPI_OP ("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP, ARGI_CREATE_BYTE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), /* 36 */ ACPI_OP ("CreateBitField", ARGP_CREATE_BIT_FIELD_OP, ARGI_CREATE_BIT_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), /* 37 */ ACPI_OP ("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), -/* 38 */ ACPI_OP ("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL), -/* 39 */ ACPI_OP ("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL), -/* 3A */ ACPI_OP ("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), -/* 3B */ ACPI_OP ("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL), -/* 3C */ ACPI_OP ("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL), -/* 3D */ ACPI_OP ("LLess", ARGP_LLESS_OP, ARGI_LLESS_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL), +/* 38 */ ACPI_OP ("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), +/* 39 */ ACPI_OP ("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), +/* 3A */ ACPI_OP ("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), +/* 3B */ ACPI_OP ("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), +/* 3C */ ACPI_OP ("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), +/* 3D */ ACPI_OP ("LLess", ARGP_LLESS_OP, ARGI_LLESS_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), /* 3E */ ACPI_OP ("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), /* 3F */ ACPI_OP ("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), /* 40 */ ACPI_OP ("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), @@ -522,7 +522,7 @@ /* 42 */ ACPI_OP ("Return", ARGP_RETURN_OP, ARGI_RETURN_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), /* 43 */ ACPI_OP ("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), /* 44 */ ACPI_OP ("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), -/* 45 */ ACPI_OP ("Ones", ARGP_ONES_OP, ARGI_ONES_OP, INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, 0), +/* 45 */ ACPI_OP ("Ones", ARGP_ONES_OP, ARGI_ONES_OP, INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), /* Prefixed opcodes (Two-byte opcodes with a prefix op) */ @@ -538,8 +538,8 @@ /* 4F */ ACPI_OP ("Wait", ARGP_WAIT_OP, ARGI_WAIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R), /* 50 */ ACPI_OP ("Reset", ARGP_RESET_OP, ARGI_RESET_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), /* 51 */ ACPI_OP ("Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), -/* 52 */ ACPI_OP ("FromBCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), -/* 53 */ ACPI_OP ("ToBCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), +/* 52 */ ACPI_OP ("FromBCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 53 */ ACPI_OP ("ToBCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 54 */ ACPI_OP ("Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), /* 55 */ ACPI_OP ("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP, INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, 0), /* 56 */ ACPI_OP ("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP, INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, 0), @@ -555,9 +555,9 @@ /* Internal opcodes that map to invalid AML opcodes */ -/* 60 */ ACPI_OP ("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS), -/* 61 */ ACPI_OP ("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS), -/* 62 */ ACPI_OP ("LGreaterEqual", ARGP_LGREATEREQUAL_OP, ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS), +/* 60 */ ACPI_OP ("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), +/* 61 */ ACPI_OP ("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), +/* 62 */ ACPI_OP ("LGreaterEqual", ARGP_LGREATEREQUAL_OP, ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), /* 63 */ ACPI_OP ("[NamePath]", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP, INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE ), /* 64 */ ACPI_OP ("[MethodCall]", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP, ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL, AML_TYPE_METHOD_CALL, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE), /* 65 */ ACPI_OP ("[ByteList]", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP, ACPI_TYPE_ANY, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, 0), @@ -573,18 +573,18 @@ /* ACPI 2.0 opcodes */ -/* 6E */ ACPI_OP ("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, 0), +/* 6E */ ACPI_OP ("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT), /* 6F */ ACPI_OP ("Package /*Var*/", ARGP_VAR_PACKAGE_OP, ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER), -/* 70 */ ACPI_OP ("ConcatenateResTemplate", ARGP_CONCAT_RES_OP, ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R), -/* 71 */ ACPI_OP ("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R), +/* 70 */ ACPI_OP ("ConcatenateResTemplate", ARGP_CONCAT_RES_OP, ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), +/* 71 */ ACPI_OP ("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), /* 72 */ ACPI_OP ("CreateQWordField", ARGP_CREATE_QWORD_FIELD_OP,ARGI_CREATE_QWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), -/* 73 */ ACPI_OP ("ToBuffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), -/* 74 */ ACPI_OP ("ToDecimalString", ARGP_TO_DEC_STR_OP, ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), -/* 75 */ ACPI_OP ("ToHexString", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), -/* 76 */ ACPI_OP ("ToInteger", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), -/* 77 */ ACPI_OP ("ToString", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R), +/* 73 */ ACPI_OP ("ToBuffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 74 */ ACPI_OP ("ToDecimalString", ARGP_TO_DEC_STR_OP, ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 75 */ ACPI_OP ("ToHexString", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 76 */ ACPI_OP ("ToInteger", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), +/* 77 */ ACPI_OP ("ToString", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), /* 78 */ ACPI_OP ("CopyObject", ARGP_COPY_OP, ARGI_COPY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), -/* 79 */ ACPI_OP ("Mid", ARGP_MID_OP, ARGI_MID_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R, AML_FLAGS_EXEC_3A_1T_1R), +/* 79 */ ACPI_OP ("Mid", ARGP_MID_OP, ARGI_MID_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R, AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT), /* 7A */ ACPI_OP ("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), /* 7B */ ACPI_OP ("LoadTable", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R), /* 7C */ ACPI_OP ("DataTableRegion", ARGP_DATA_REGION_OP, ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), @@ -702,6 +702,7 @@ } /* Else fall through to error case below */ + /*lint -fallthrough */ default: @@ -749,5 +750,4 @@ #endif } - diff -Nru a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c --- a/drivers/acpi/parser/psparse.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/parser/psparse.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psparse - Parser top level AML parse routines - * $Revision: 121 $ + * $Revision: 127 $ * *****************************************************************************/ @@ -38,15 +38,13 @@ #include "acdispat.h" #include "amlcode.h" #include "acnamesp.h" -#include "acdebug.h" #include "acinterp.h" #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME ("psparse") -u32 acpi_gbl_depth = 0; -extern u32 acpi_gbl_scope_depth; +static u32 acpi_gbl_depth = 0; /******************************************************************************* @@ -172,13 +170,13 @@ * PARAMETERS: Walk_state - Current State * Op - Op to complete * - * RETURN: TRUE if Op and subtree was deleted + * RETURN: None. * * DESCRIPTION: Perform any cleanup at the completion of an Op. * ******************************************************************************/ -u8 +void acpi_ps_complete_this_op ( acpi_walk_state *walk_state, acpi_parse_object *op) @@ -196,7 +194,7 @@ /* Check for null Op, can happen if AML code is corrupt */ if (!op) { - return_VALUE (TRUE); + return_VOID; } /* Delete this op and the subtree below it if asked to */ @@ -205,12 +203,12 @@ (walk_state->op_info->class != AML_CLASS_ARGUMENT)) { /* Make sure that we only delete this subtree */ - if (op->parent) { + if (op->common.parent) { /* * Check if we need to replace the operator and its subtree * with a return value op (placeholder op) */ - parent_info = acpi_ps_get_opcode_info (op->parent->opcode); + parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode); switch (parent_info->class) { case AML_CLASS_CONTROL: @@ -224,7 +222,7 @@ */ replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); if (!replacement_op) { - return_VALUE (FALSE); + return_VOID; } break; @@ -234,31 +232,29 @@ * These opcodes contain Term_arg operands. The current * op must be replaced by a placeholder return op */ - if ((op->parent->opcode == AML_REGION_OP) || - (op->parent->opcode == AML_DATA_REGION_OP) || - (op->parent->opcode == AML_BUFFER_OP) || - (op->parent->opcode == AML_PACKAGE_OP) || - (op->parent->opcode == AML_VAR_PACKAGE_OP)) { + if ((op->common.parent->common.aml_opcode == AML_REGION_OP) || + (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) || + (op->common.parent->common.aml_opcode == AML_BUFFER_OP) || + (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); if (!replacement_op) { - return_VALUE (FALSE); + return_VOID; } } - if ((op->parent->opcode == AML_NAME_OP) && + if ((op->common.parent->common.aml_opcode == AML_NAME_OP) && (walk_state->descending_callback != acpi_ds_exec_begin_op)) { - if ((op->opcode == AML_BUFFER_OP) || - (op->opcode == AML_PACKAGE_OP) || - (op->opcode == AML_VAR_PACKAGE_OP)) { - replacement_op = acpi_ps_alloc_op (op->opcode); + if ((op->common.aml_opcode == AML_BUFFER_OP) || + (op->common.aml_opcode == AML_PACKAGE_OP) || + (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) { + replacement_op = acpi_ps_alloc_op (op->common.aml_opcode); if (!replacement_op) { - return_VALUE (FALSE); + return_VOID; } - ((acpi_parse2_object *) replacement_op)->data = - ((acpi_parse2_object *) op)->data; - ((acpi_parse2_object *) replacement_op)->length = - ((acpi_parse2_object *) op)->length; + replacement_op->named.data = op->named.data; + replacement_op->named.length = op->named.length; } } break; @@ -266,25 +262,25 @@ default: replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); if (!replacement_op) { - return_VALUE (FALSE); + return_VOID; } } /* We must unlink this op from the parent tree */ - prev = op->parent->value.arg; + prev = op->common.parent->common.value.arg; if (prev == op) { /* This op is the first in the list */ if (replacement_op) { - replacement_op->parent = op->parent; - replacement_op->value.arg = NULL; - replacement_op->node = op->node; - op->parent->value.arg = replacement_op; - replacement_op->next = op->next; + replacement_op->common.parent = op->common.parent; + replacement_op->common.value.arg = NULL; + replacement_op->common.node = op->common.node; + op->common.parent->common.value.arg = replacement_op; + replacement_op->common.next = op->common.next; } else { - op->parent->value.arg = op->next; + op->common.parent->common.value.arg = op->common.next; } } @@ -293,18 +289,18 @@ else while (prev) { /* Traverse all siblings in the parent's argument list */ - next = prev->next; + next = prev->common.next; if (next == op) { if (replacement_op) { - replacement_op->parent = op->parent; - replacement_op->value.arg = NULL; - replacement_op->node = op->node; - prev->next = replacement_op; - replacement_op->next = op->next; + replacement_op->common.parent = op->common.parent; + replacement_op->common.value.arg = NULL; + replacement_op->common.node = op->common.node; + prev->common.next = replacement_op; + replacement_op->common.next = op->common.next; next = NULL; } else { - prev->next = op->next; + prev->common.next = op->common.next; next = NULL; } } @@ -317,13 +313,13 @@ acpi_ps_delete_parse_tree (op); - return_VALUE (TRUE); + return_VOID; } - return_VALUE (FALSE); + return_VOID; #else - return (FALSE); + return; #endif } @@ -422,7 +418,7 @@ status = AE_CTRL_TRANSFER; walk_state->prev_op = op; walk_state->method_call_op = op; - walk_state->method_call_node = (op->value.arg)->node; + walk_state->method_call_node = (op->common.value.arg)->common.node; /* Will return value (if any) be used by the caller? */ @@ -469,6 +465,10 @@ ACPI_FUNCTION_TRACE_PTR ("Ps_parse_loop", walk_state); + if (walk_state->descending_callback == NULL) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + parser_state = &walk_state->parser_state; walk_state->arg_types = 0; @@ -483,8 +483,8 @@ * was just completed */ if ((parser_state->scope->parse_scope.op) && - ((parser_state->scope->parse_scope.op->opcode == AML_IF_OP) || - (parser_state->scope->parse_scope.op->opcode == AML_WHILE_OP)) && + ((parser_state->scope->parse_scope.op->common.aml_opcode == AML_IF_OP) || + (parser_state->scope->parse_scope.op->common.aml_opcode == AML_WHILE_OP)) && (walk_state->control_state) && (walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING)) { @@ -526,12 +526,12 @@ * Iterative parsing loop, while there is more aml to process: */ while ((parser_state->aml < parser_state->aml_end) || (op)) { + aml_op_start = parser_state->aml; if (!op) { /* Get the next opcode from the AML stream */ - aml_op_start = parser_state->aml; - walk_state->aml_offset = parser_state->aml - parser_state->aml_start; - walk_state->opcode = acpi_ps_peek_opcode (parser_state); + walk_state->aml_offset = ACPI_PTR_DIFF (parser_state->aml, parser_state->aml_start); + walk_state->opcode = acpi_ps_peek_opcode (parser_state); /* * First cut to determine what we have found: @@ -578,8 +578,8 @@ /* Create Op structure and append to parent's argument list */ if (walk_state->op_info->flags & AML_NAMED) { - pre_op.value.arg = NULL; - pre_op.opcode = walk_state->opcode; + pre_op.common.value.arg = NULL; + pre_op.common.aml_opcode = walk_state->opcode; while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) != ARGP_NAME) { arg = acpi_ps_get_next_arg (parser_state, @@ -593,39 +593,37 @@ INCREMENT_ARG_LIST (walk_state->arg_types); - if (walk_state->descending_callback != NULL) { - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - walk_state->op = NULL; + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + walk_state->op = NULL; - status = walk_state->descending_callback (walk_state, &op); - if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "During name lookup/catalog, %s\n", - acpi_format_exception (status))); - goto close_this_op; - } + status = walk_state->descending_callback (walk_state, &op); + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "During name lookup/catalog, %s\n", + acpi_format_exception (status))); + goto close_this_op; + } - if (op == NULL) { - continue; - } + if (op == NULL) { + continue; + } - status = acpi_ps_next_parse_state (walk_state, op, status); - if (status == AE_CTRL_PENDING) { - status = AE_OK; - goto close_this_op; - } + status = acpi_ps_next_parse_state (walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_OK; + goto close_this_op; + } - if (ACPI_FAILURE (status)) { - goto close_this_op; - } + if (ACPI_FAILURE (status)) { + goto close_this_op; } - acpi_ps_append_arg (op, pre_op.value.arg); + acpi_ps_append_arg (op, pre_op.common.value.arg); acpi_gbl_depth++; - if (op->opcode == AML_REGION_OP) { + if (op->common.aml_opcode == AML_REGION_OP) { /* * Defer final parsing of an Operation_region body, * because we don't have enough info in the first pass @@ -638,8 +636,8 @@ * * (Length is unknown until parse of the body complete) */ - ((acpi_parse2_object * ) op)->data = aml_op_start; - ((acpi_parse2_object * ) op)->length = 0; + op->named.data = aml_op_start; + op->named.length = 0; } } else { @@ -656,8 +654,8 @@ * Backup to beginning of Create_xXXfield declaration * Body_length is unknown until we parse the body */ - ((acpi_parse2_object * ) op)->data = aml_op_start; - ((acpi_parse2_object * ) op)->length = 0; + op->named.data = aml_op_start; + op->named.length = 0; } acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op); @@ -682,12 +680,13 @@ } } - op->aml_offset = walk_state->aml_offset; + op->common.aml_offset = walk_state->aml_offset; if (walk_state->op_info) { ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, - "Opcode %4.4X [%s] Op %p Aml %p Aml_offset %5.5X\n", - op->opcode, walk_state->op_info->name, op, parser_state->aml, op->aml_offset)); + "Opcode %4.4hX [%s] Op %p Aml %p Aml_offset %5.5X\n", + op->common.aml_opcode, walk_state->op_info->name, + op, parser_state->aml, op->common.aml_offset)); } } @@ -699,7 +698,7 @@ if (walk_state->arg_types) /* Are there any arguments that must be processed? */ { /* Get arguments */ - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ case AML_WORD_OP: /* AML_WORDDATA_ARG */ case AML_DWORD_OP: /* AML_DWORDATA_ARG */ @@ -724,19 +723,20 @@ /* Op is not a constant or string, append each argument */ while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && !walk_state->arg_count) { - walk_state->aml_offset = parser_state->aml - parser_state->aml_start; + walk_state->aml_offset = ACPI_PTR_DIFF (parser_state->aml, + parser_state->aml_start); arg = acpi_ps_get_next_arg (parser_state, GET_CURRENT_ARG_TYPE (walk_state->arg_types), &walk_state->arg_count); if (arg) { - arg->aml_offset = walk_state->aml_offset; + arg->common.aml_offset = walk_state->aml_offset; acpi_ps_append_arg (op, arg); } INCREMENT_ARG_LIST (walk_state->arg_types); } - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_METHOD_OP: /* For a method, save the length and address of the body */ @@ -746,9 +746,8 @@ * because we don't have enough info in the first pass * to parse them correctly. */ - ((acpi_parse2_object * ) op)->data = parser_state->aml; - ((acpi_parse2_object * ) op)->length = (u32) (parser_state->pkg_end - - parser_state->aml); + op->named.data = parser_state->aml; + op->named.length = (u32) (parser_state->pkg_end - parser_state->aml); /* * Skip body of method. For Op_regions, we must continue * parsing because the opregion is not a standalone @@ -762,17 +761,16 @@ case AML_PACKAGE_OP: case AML_VAR_PACKAGE_OP: - if ((op->parent) && - (op->parent->opcode == AML_NAME_OP) && + if ((op->common.parent) && + (op->common.parent->common.aml_opcode == AML_NAME_OP) && (walk_state->descending_callback != acpi_ds_exec_begin_op)) { /* * Skip parsing of * because we don't have enough info in the first pass * to parse them correctly. */ - ((acpi_parse2_object * ) op)->data = aml_op_start; - ((acpi_parse2_object * ) op)->length = (u32) (parser_state->pkg_end - - aml_op_start); + op->named.data = aml_op_start; + op->named.length = (u32) (parser_state->pkg_end - aml_op_start); /* * Skip body */ @@ -787,6 +785,10 @@ walk_state->control_state->control.package_end = parser_state->pkg_end; } break; + + default: + /* No action for all other opcodes */ + break; } break; } @@ -797,20 +799,23 @@ if (walk_state->arg_count) { /* There are arguments (complex ones), push Op and prepare for argument */ - acpi_ps_push_scope (parser_state, op, walk_state->arg_types, walk_state->arg_count); + status = acpi_ps_push_scope (parser_state, op, walk_state->arg_types, walk_state->arg_count); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } op = NULL; continue; } /* All arguments have been processed -- Op is complete, prepare for next */ - walk_state->op_info = acpi_ps_get_opcode_info (op->opcode); + walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); if (walk_state->op_info->flags & AML_NAMED) { if (acpi_gbl_depth) { acpi_gbl_depth--; } - if (op->opcode == AML_REGION_OP) { + if (op->common.aml_opcode == AML_REGION_OP) { /* * Skip parsing of control method or opregion body, * because we don't have enough info in the first pass @@ -819,8 +824,7 @@ * Completed parsing an Op_region declaration, we now * know the length. */ - ((acpi_parse2_object * ) op)->length = (u32) (parser_state->aml - - ((acpi_parse2_object * ) op)->data); + op->named.length = (u32) (parser_state->aml - op->named.data); } } @@ -831,15 +835,14 @@ * * Body_length is unknown until we parse the body */ - ((acpi_parse2_object * ) op)->length = (u32) (parser_state->aml - - ((acpi_parse2_object * ) op)->data); + op->named.length = (u32) (parser_state->aml - op->named.data); } /* This op complete, notify the dispatcher */ if (walk_state->ascending_callback != NULL) { walk_state->op = op; - walk_state->opcode = op->opcode; + walk_state->opcode = op->common.aml_opcode; status = walk_state->ascending_callback (walk_state); status = acpi_ps_next_parse_state (walk_state, op, status); @@ -856,11 +859,10 @@ */ parser_state->scope->parse_scope.arg_count--; - /* Close this Op (may result in parse subtree deletion) */ + /* Close this Op (will result in parse subtree deletion) */ - if (acpi_ps_complete_this_op (walk_state, op)) { - op = NULL; - } + acpi_ps_complete_this_op (walk_state, op); + op = NULL; switch (status) { case AE_OK: @@ -882,8 +884,8 @@ acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); walk_state->op = op; - walk_state->op_info = acpi_ps_get_opcode_info (op->opcode); - walk_state->opcode = op->opcode; + walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); + walk_state->opcode = op->common.aml_opcode; status = walk_state->ascending_callback (walk_state); status = acpi_ps_next_parse_state (walk_state, op, status); @@ -899,15 +901,15 @@ /* Pop off scopes until we find the While */ - while (!op || (op->opcode != AML_WHILE_OP)) { + while (!op || (op->common.aml_opcode != AML_WHILE_OP)) { acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); } /* Close this iteration of the While loop */ walk_state->op = op; - walk_state->op_info = acpi_ps_get_opcode_info (op->opcode); - walk_state->opcode = op->opcode; + walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); + walk_state->opcode = op->common.aml_opcode; status = walk_state->ascending_callback (walk_state); status = acpi_ps_next_parse_state (walk_state, op, status); @@ -983,8 +985,8 @@ if (op) { if (walk_state->ascending_callback != NULL) { walk_state->op = op; - walk_state->op_info = acpi_ps_get_opcode_info (op->opcode); - walk_state->opcode = op->opcode; + walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); + walk_state->opcode = op->common.aml_opcode; status = walk_state->ascending_callback (walk_state); status = acpi_ps_next_parse_state (walk_state, op, status); @@ -1125,7 +1127,13 @@ * there's lots of cleanup to do */ if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) { - acpi_ds_terminate_control_method (walk_state); + status = acpi_ds_terminate_control_method (walk_state); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not terminate control method properly\n")); + status = AE_OK; + + /* Ignore error and continue */ + } } /* Delete this walk state and all linked control states */ @@ -1147,8 +1155,10 @@ * If the method return value is not used by the parent, * The object is deleted */ - acpi_ds_restart_control_method (walk_state, previous_walk_state->return_desc); - walk_state->walk_type |= ACPI_WALK_METHOD_RESTART; + status = acpi_ds_restart_control_method (walk_state, previous_walk_state->return_desc); + if (ACPI_SUCCESS (status)) { + walk_state->walk_type |= ACPI_WALK_METHOD_RESTART; + } } else { /* On error, delete any return object */ @@ -1181,7 +1191,7 @@ /* Normal exit */ acpi_ex_release_all_mutexes (thread); - acpi_ut_delete_generic_state ((acpi_generic_state *) thread); + acpi_ut_delete_generic_state (ACPI_CAST_PTR (acpi_generic_state, thread)); acpi_gbl_current_walk_list = prev_walk_list; return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c --- a/drivers/acpi/parser/pstree.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/parser/pstree.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: pstree - Parser op tree manipulation/traversal/search - * $Revision: 37 $ + * $Revision: 39 $ * *****************************************************************************/ @@ -59,7 +59,7 @@ /* Get the info structure for this opcode */ - op_info = acpi_ps_get_opcode_info (op->opcode); + op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); if (op_info->class == AML_CLASS_UNKNOWN) { /* Invalid opcode or ASCII character */ @@ -76,10 +76,10 @@ /* Get the requested argument object */ - arg = op->value.arg; + arg = op->common.value.arg; while (arg && argn) { argn--; - arg = arg->next; + arg = arg->common.next; } return (arg); @@ -117,11 +117,12 @@ /* Get the info structure for this opcode */ - op_info = acpi_ps_get_opcode_info (op->opcode); + op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); if (op_info->class == AML_CLASS_UNKNOWN) { /* Invalid opcode */ - ACPI_REPORT_ERROR (("Ps_append_arg: Invalid AML Opcode: 0x%2.2X\n", op->opcode)); + ACPI_REPORT_ERROR (("Ps_append_arg: Invalid AML Opcode: 0x%2.2X\n", + op->common.aml_opcode)); return; } @@ -136,28 +137,28 @@ /* Append the argument to the linked argument list */ - if (op->value.arg) { + if (op->common.value.arg) { /* Append to existing argument list */ - prev_arg = op->value.arg; - while (prev_arg->next) { - prev_arg = prev_arg->next; + prev_arg = op->common.value.arg; + while (prev_arg->common.next) { + prev_arg = prev_arg->common.next; } - prev_arg->next = arg; + prev_arg->common.next = arg; } else { /* No argument list, this will be the first argument */ - op->value.arg = arg; + op->common.value.arg = arg; } /* Set the parent in this arg and any args linked after it */ while (arg) { - arg->parent = op; - arg = arg->next; + arg->common.parent = op; + arg = arg->common.next; } } @@ -184,7 +185,7 @@ ACPI_FUNCTION_ENTRY (); - switch (op->opcode) { + switch (op->common.aml_opcode) { case AML_SCOPE_OP: case AML_ELSE_OP: case AML_DEVICE_OP: @@ -219,6 +220,10 @@ child = acpi_ps_get_arg (op, 3); break; + + default: + /* All others have no children */ + break; } return (child); @@ -265,19 +270,19 @@ /* look for a sibling */ - next = op->next; + next = op->common.next; if (next) { return (next); } /* look for a sibling of parent */ - parent = op->parent; + parent = op->common.parent; while (parent) { arg = acpi_ps_get_arg (parent, 0); while (arg && (arg != origin) && (arg != op)) { - arg = arg->next; + arg = arg->common.next; } if (arg == origin) { @@ -286,13 +291,14 @@ return (NULL); } - if (parent->next) { + if (parent->common.next) { /* found sibling of parent */ - return (parent->next); + + return (parent->common.next); } op = parent; - parent = parent->parent; + parent = parent->common.parent; } return (next); diff -Nru a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c --- a/drivers/acpi/parser/psutils.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/parser/psutils.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psutils - Parser miscellaneous utilities (Parser only) - * $Revision: 50 $ + * $Revision: 51 $ * *****************************************************************************/ @@ -54,11 +54,11 @@ ACPI_FUNCTION_ENTRY (); - op->data_type = ACPI_DESC_TYPE_PARSER; - op->opcode = opcode; + op->common.data_type = ACPI_DESC_TYPE_PARSER; + op->common.aml_opcode = opcode; - ACPI_DEBUG_ONLY_MEMBERS (ACPI_STRNCPY (op->op_name, - (acpi_ps_get_opcode_info (opcode))->name, sizeof (op->op_name))); + ACPI_DEBUG_ONLY_MEMBERS (ACPI_STRNCPY (op->common.aml_op_name, + (acpi_ps_get_opcode_info (opcode))->name, sizeof (op->common.aml_op_name))); } @@ -94,23 +94,23 @@ /* Allocate the minimum required size object */ if (op_info->flags & AML_DEFER) { - size = sizeof (acpi_parse2_object); + size = sizeof (ACPI_PARSE_OBJ_NAMED); flags = ACPI_PARSEOP_DEFERRED; } else if (op_info->flags & AML_NAMED) { - size = sizeof (acpi_parse2_object); + size = sizeof (ACPI_PARSE_OBJ_NAMED); flags = ACPI_PARSEOP_NAMED; } else if (opcode == AML_INT_BYTELIST_OP) { - size = sizeof (acpi_parse2_object); + size = sizeof (ACPI_PARSE_OBJ_NAMED); flags = ACPI_PARSEOP_BYTELIST; } else { - size = sizeof (acpi_parse_object); + size = sizeof (ACPI_PARSE_OBJ_COMMON); flags = ACPI_PARSEOP_GENERIC; } - if (size == sizeof (acpi_parse_object)) { + if (size == sizeof (ACPI_PARSE_OBJ_COMMON)) { /* * The generic op is by far the most common (16 to 1) */ @@ -124,7 +124,7 @@ if (op) { acpi_ps_init_op (op, opcode); - op->flags = flags; + op->common.flags = flags; } return (op); @@ -151,11 +151,11 @@ ACPI_FUNCTION_NAME ("Ps_free_op"); - if (op->opcode == AML_INT_RETURN_VALUE_OP) { + if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n", op)); } - if (op->flags == ACPI_PARSEOP_GENERIC) { + if (op->common.flags == ACPI_PARSEOP_GENERIC) { acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE, op); } else { @@ -231,13 +231,13 @@ /* The "generic" object has no name associated with it */ - if (op->flags & ACPI_PARSEOP_GENERIC) { + if (op->common.flags & ACPI_PARSEOP_GENERIC) { return (0); } /* Only the "Extended" parse objects have a name */ - return (((acpi_parse2_object *) op)->name); + return (op->named.name); } @@ -252,10 +252,10 @@ /* The "generic" object has no name associated with it */ - if (op->flags & ACPI_PARSEOP_GENERIC) { + if (op->common.flags & ACPI_PARSEOP_GENERIC) { return; } - ((acpi_parse2_object *) op)->name = name; + op->named.name = name; } diff -Nru a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c --- a/drivers/acpi/parser/pswalk.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/parser/pswalk.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: pswalk - Parser routines to walk parsed op tree(s) - * $Revision: 63 $ + * $Revision: 67 $ * *****************************************************************************/ @@ -25,11 +25,8 @@ #include "acpi.h" -#include "amlcode.h" #include "acparser.h" #include "acdispat.h" -#include "acnamesp.h" -#include "acinterp.h" #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME ("pswalk") @@ -84,12 +81,12 @@ * No more children, this Op is complete. Save Next and Parent * in case the Op object gets deleted by the callback routine */ - next = op->next; - parent = op->parent; + next = op->common.next; + parent = op->common.parent; walk_state->op = op; - walk_state->op_info = acpi_ps_get_opcode_info (op->opcode); - walk_state->opcode = op->opcode; + walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); + walk_state->opcode = op->common.aml_opcode; status = ascending_callback (walk_state); @@ -142,12 +139,12 @@ while (parent) { /* We are moving up the tree, therefore this parent Op is complete */ - grand_parent = parent->parent; - next = parent->next; + grand_parent = parent->common.parent; + next = parent->common.next; walk_state->op = parent; - walk_state->op_info = acpi_ps_get_opcode_info (parent->opcode); - walk_state->opcode = parent->opcode; + walk_state->op_info = acpi_ps_get_opcode_info (parent->common.aml_opcode); + walk_state->opcode = parent->common.aml_opcode; status = ascending_callback (walk_state); @@ -238,6 +235,7 @@ { acpi_walk_state *walk_state; ACPI_THREAD_STATE *thread; + acpi_status status; ACPI_FUNCTION_TRACE_PTR ("Ps_delete_parse_tree", subtree_root); @@ -254,7 +252,6 @@ return_VOID; } - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, thread); if (!walk_state) { return_VOID; @@ -274,13 +271,16 @@ /* Visit all nodes in the subtree */ while (walk_state->next_op) { - acpi_ps_get_next_walk_op (walk_state, walk_state->next_op, + status = acpi_ps_get_next_walk_op (walk_state, walk_state->next_op, acpi_ps_delete_completed_op); + if (ACPI_FAILURE (status)) { + break; + } } /* We are done with this walk */ - acpi_ut_delete_generic_state ((acpi_generic_state *) thread); + acpi_ut_delete_generic_state (ACPI_CAST_PTR (acpi_generic_state, thread)); acpi_ds_delete_walk_state (walk_state); return_VOID; diff -Nru a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c --- a/drivers/acpi/parser/psxface.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/parser/psxface.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psxface - Parser external interfaces - * $Revision: 61 $ + * $Revision: 64 $ * *****************************************************************************/ @@ -140,7 +140,6 @@ status = acpi_ps_parse_aml (walk_state); acpi_ps_delete_parse_tree (op); - /* * 2) Execute the method. Performs second pass parse simultaneously */ @@ -158,12 +157,11 @@ /* Init new op with the method name and pointer back to the NS node */ acpi_ps_set_name (op, method_node->name.integer); - op->node = method_node; + op->common.node = method_node; /* Create and initialize a new walk state */ - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, - NULL, NULL, NULL); + walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } @@ -185,7 +183,9 @@ /* Take away the extra reference that we gave the parameters above */ for (i = 0; params[i]; i++) { - acpi_ut_update_object_reference (params[i], REF_DECREMENT); + /* Ignore errors, just do them all */ + + (void) acpi_ut_update_object_reference (params[i], REF_DECREMENT); } } diff -Nru a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/pci_bind.c Sun Jun 2 18:44:58 2002 @@ -0,0 +1,309 @@ +/* + * pci_bind.c - ACPI PCI Device Binding ($Revision: 2 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_PCI_COMPONENT +ACPI_MODULE_NAME ("pci_bind") + +#define PREFIX "ACPI: " + + +struct acpi_pci_data { + acpi_pci_id id; + struct pci_bus *bus; + struct pci_dev *dev; +}; + + +void +acpi_pci_data_handler ( + acpi_handle handle, + u32 function, + void *context) +{ + ACPI_FUNCTION_TRACE("acpi_pci_data_handler"); + + /* TBD: Anything we need to do here? */ + + return_VOID; +} + + +/** + * acpi_os_get_pci_id + * ------------------ + * This function is used by the ACPI Interpreter (a.k.a. Core Subsystem) + * to resolve PCI information for ACPI-PCI devices defined in the namespace. + * This typically occurs when resolving PCI operation region information. + */ +acpi_status +acpi_os_get_pci_id ( + acpi_handle handle, + acpi_pci_id *id) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_device *device = NULL; + struct acpi_pci_data *data = NULL; + + ACPI_FUNCTION_TRACE("acpi_os_get_pci_id"); + + if (!id) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + result = acpi_bus_get_device(handle, &device); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Invalid ACPI Bus context for device %s\n", + acpi_device_bid(device))); + return_ACPI_STATUS(AE_NOT_EXIST); + } + + status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data); + if (ACPI_FAILURE(status) || !data || !data->dev) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Invalid ACPI-PCI context for device %s\n", + acpi_device_bid(device))); + return_ACPI_STATUS(status); + } + + *id = data->id; + + /* + id->segment = data->id.segment; + id->bus = data->id.bus; + id->device = data->id.device; + id->function = data->id.function; + */ + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Device %s has PCI address %02x:%02x:%02x.%02x\n", + acpi_device_bid(device), id->segment, id->bus, + id->device, id->function)); + + return_ACPI_STATUS(AE_OK); +} + + +int +acpi_pci_bind ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_pci_data *data = NULL; + struct acpi_pci_data *pdata = NULL; + char pathname[PATHNAME_MAX] = {0}; + acpi_buffer buffer = {PATHNAME_MAX, pathname}; + acpi_handle handle = NULL; + + ACPI_FUNCTION_TRACE("acpi_pci_bind"); + + if (!device || !device->parent) + return_VALUE(-EINVAL); + + data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); + if (!data) + return_VALUE(-ENOMEM); + memset(data, 0, sizeof(struct acpi_pci_data)); + + acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n", + pathname)); + + /* + * Segment & Bus + * ------------- + * These are obtained via the parent device's ACPI-PCI context. + */ + status = acpi_get_data(device->parent->handle, acpi_pci_data_handler, + (void**) &pdata); + if (ACPI_FAILURE(status) || !pdata || !pdata->bus) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Invalid ACPI-PCI context for parent device %s\n", + acpi_device_bid(device->parent))); + result = -ENODEV; + goto end; + } + data->id.segment = pdata->id.segment; + data->id.bus = pdata->bus->number; + + /* + * Device & Function + * ----------------- + * These are simply obtained from the device's _ADR method. Note + * that a value of zero is valid. + */ + data->id.device = device->pnp.bus_address >> 16; + data->id.function = device->pnp.bus_address & 0xFFFF; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %02x:%02x:%02x.%02x\n", + data->id.segment, data->id.bus, data->id.device, + data->id.function)); + + /* + * TBD: Support slot devices (e.g. function=0xFFFF). + */ + + /* + * Locate PCI Device + * ----------------- + * Locate matching device in PCI namespace. If it doesn't exist + * this typically means that the device isn't currently inserted + * (e.g. docking station, port replicator, etc.). + */ + data->dev = pci_find_slot(data->id.bus, PCI_DEVFN(data->id.device, data->id.function)); + if (!data->dev) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Device %02x:%02x:%02x.%02x not present in PCI namespace\n", + data->id.segment, data->id.bus, + data->id.device, data->id.function)); + result = -ENODEV; + goto end; + } + if (!data->dev->bus) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Device %02x:%02x:%02x.%02x has invalid 'bus' field\n", + data->id.segment, data->id.bus, + data->id.device, data->id.function)); + result = -ENODEV; + goto end; + } + + /* + * PCI Bridge? + * ----------- + * If so, set the 'bus' field and install the 'bind' function to + * facilitate callbacks for all of its children. + */ + if (data->dev->subordinate) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Device %02x:%02x:%02x.%02x is a PCI bridge\n", + data->id.segment, data->id.bus, + data->id.device, data->id.function)); + data->bus = data->dev->subordinate; + device->ops.bind = acpi_pci_bind; + } + + /* + * Attach ACPI-PCI Context + * ----------------------- + * Thus binding the ACPI and PCI devices. + */ + status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to attach ACPI-PCI context to device %s\n", + acpi_device_bid(device))); + result = -ENODEV; + goto end; + } + + /* + * PCI Routing Table + * ----------------- + * Evaluate and parse _PRT, if exists. This code is independent of + * PCI bridges (above) to allow parsing of _PRT objects within the + * scope of non-bridge devices. Note that _PRTs within the scope of + * a PCI bridge assume the bridge's subordinate bus number. + * + * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? + */ + status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); + if (ACPI_SUCCESS(status)) { + if (data->bus) /* PCI-PCI bridge */ + acpi_pci_irq_add_prt(device->handle, data->id.segment, + data->bus->number); + else /* non-bridge PCI device */ + acpi_pci_irq_add_prt(device->handle, data->id.segment, + data->id.bus); + } + +end: + if (result) + kfree(data); + + return_VALUE(result); +} + + +int +acpi_pci_bind_root ( + struct acpi_device *device, + acpi_pci_id *id, + struct pci_bus *bus) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_pci_data *data = NULL; + char pathname[PATHNAME_MAX] = {0}; + acpi_buffer buffer = {PATHNAME_MAX, pathname}; + + ACPI_FUNCTION_TRACE("acpi_pci_bind_root"); + + if (!device || !id || !bus) + return_VALUE(-EINVAL); + + data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); + if (!data) + return_VALUE(-ENOMEM); + memset(data, 0, sizeof(struct acpi_pci_data)); + + data->id = *id; + data->bus = bus; + device->ops.bind = acpi_pci_bind; + + acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to " + "%02x:%02x\n", pathname, id->segment, id->bus)); + + status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to attach ACPI-PCI context to device %s\n", + pathname)); + result = -ENODEV; + goto end; + } + +end: + if (result != 0) + kfree(data); + + return_VALUE(result); +} diff -Nru a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/pci_irq.c Sun Jun 2 18:44:58 2002 @@ -0,0 +1,387 @@ +/* + * pci_irq.c - ACPI PCI Interrupt Routing ($Revision: 7 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * Copyright (C) 2002 Dominik Brodowski + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_PCI_COMPONENT +ACPI_MODULE_NAME ("pci_irq") + +#define PREFIX "PCI: " + +struct acpi_prt_list acpi_prt; + +#ifdef CONFIG_X86 +extern void eisa_set_level_irq(unsigned int irq); +#endif + + +/* -------------------------------------------------------------------------- + PCI IRQ Routing Table (PRT) Support + -------------------------------------------------------------------------- */ + +static struct acpi_prt_entry * +acpi_pci_irq_find_prt_entry ( + int segment, + int bus, + int device, + int pin) +{ + struct list_head *node = NULL; + struct acpi_prt_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_pci_irq_find_prt_entry"); + + /* + * Parse through all PRT entries looking for a match on the specified + * PCI device's segment, bus, device, and pin (don't care about func). + * + * TBD: Acquire/release lock + */ + list_for_each(node, &acpi_prt.entries) { + entry = list_entry(node, struct acpi_prt_entry, node); + if ((segment == entry->id.segment) + && (bus == entry->id.bus) + && (device == entry->id.device) + && (pin == entry->pin)) { + return_PTR(entry); + } + } + + return_PTR(NULL); +} + + +static int +acpi_pci_irq_add_entry ( + acpi_handle handle, + int segment, + int bus, + acpi_pci_routing_table *prt) +{ + struct acpi_prt_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_pci_irq_add_entry"); + + if (!prt) + return_VALUE(-EINVAL); + + entry = kmalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL); + if (!entry) + return_VALUE(-ENOMEM); + memset(entry, 0, sizeof(struct acpi_prt_entry)); + + entry->id.segment = segment; + entry->id.bus = bus; + entry->id.device = (prt->address >> 16) & 0xFFFF; + entry->id.function = prt->address & 0xFFFF; + entry->pin = prt->pin; + + /* + * Type 1: Dynamic + * --------------- + * The 'source' field specifies the PCI interrupt link device used to + * configure the IRQ assigned to this slot|dev|pin. The 'source_index' + * indicates which resource descriptor in the resource template (of + * the link device) this interrupt is allocated from. + * + * NOTE: Don't query the Link Device for IRQ information at this time + * because Link Device enumeration may not have occurred yet + * (e.g. exists somewhere 'below' this _PRT entry in the ACPI + * namespace). + */ + if (prt->source[0]) { + acpi_get_handle(handle, prt->source, &entry->link.handle); + entry->link.index = prt->source_index; + } + /* + * Type 2: Static + * -------------- + * The 'source' field is NULL, and the 'source_index' field specifies + * the IRQ value, which is hardwired to specific interrupt inputs on + * the interrupt controller. + */ + else + entry->link.index = prt->source_index; + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, + " %02X:%02X:%02X[%c] -> %s[%d]\n", + entry->id.segment, entry->id.bus, entry->id.device, + ('A' + entry->pin), prt->source, entry->link.index)); + + /* TBD: Acquire/release lock */ + list_add_tail(&entry->node, &acpi_prt.entries); + acpi_prt.count++; + + return_VALUE(0); +} + + +int +acpi_pci_irq_add_prt ( + acpi_handle handle, + int segment, + int bus) +{ + acpi_status status = AE_OK; + char pathname[PATHNAME_MAX] = {0}; + acpi_buffer buffer = {0, NULL}; + acpi_pci_routing_table *prt = NULL; + acpi_pci_routing_table *entry = NULL; + static int first_time = 1; + + ACPI_FUNCTION_TRACE("acpi_pci_irq_add_prt"); + + if (first_time) { + acpi_prt.count = 0; + INIT_LIST_HEAD(&acpi_prt.entries); + first_time = 0; + } + + /* + * NOTE: We're given a 'handle' to the _PRT object's parent device + * (either a PCI root bridge or PCI-PCI bridge). + */ + + buffer.length = sizeof(pathname); + buffer.pointer = pathname; + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + + printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n", + pathname); + + /* + * Evaluate this _PRT and add its entries to our global list (acpi_prt). + */ + + buffer.length = 0; + buffer.pointer = NULL; + status = acpi_get_irq_routing_table(handle, &buffer); + if (status != AE_BUFFER_OVERFLOW) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n", + acpi_format_exception(status))); + return_VALUE(-ENODEV); + } + + prt = kmalloc(buffer.length, GFP_KERNEL); + if (!prt) + return_VALUE(-ENOMEM); + memset(prt, 0, buffer.length); + buffer.pointer = prt; + + status = acpi_get_irq_routing_table(handle, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n", + acpi_format_exception(status))); + kfree(buffer.pointer); + return_VALUE(-ENODEV); + } + + entry = prt; + + while (entry && (entry->length > 0)) { + acpi_pci_irq_add_entry(handle, segment, bus, entry); + entry = (acpi_pci_routing_table *) + ((unsigned long) entry + entry->length); + } + + kfree(prt); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + PCI Interrupt Routing Support + -------------------------------------------------------------------------- */ + +static int +acpi_pci_irq_lookup ( + int segment, + int bus, + int device, + int pin) +{ + struct acpi_prt_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Searching for PRT entry for %02x:%02x:%02x[%c]\n", + segment, bus, device, ('A' + pin))); + + entry = acpi_pci_irq_find_prt_entry(segment, bus, device, pin); + if (!entry) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n")); + return_VALUE(0); + } + + if (!entry->irq && entry->link.handle) + entry->irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index); + else if (!entry->irq) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid static routing entry (IRQ 0)\n")); + return_VALUE(0); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", entry->irq)); + + return_VALUE(entry->irq); +} + + +static int +acpi_pci_irq_derive ( + struct pci_dev *dev, + int pin) +{ + struct pci_dev *bridge = dev; + int irq = 0; + + ACPI_FUNCTION_TRACE("acpi_pci_irq_derive"); + + if (!dev) + return_VALUE(-EINVAL); + + /* + * Attempt to derive an IRQ for this device from a parent bridge's + * PCI interrupt routing entry (a.k.a. the "bridge swizzle"). + */ + while (!irq && (bridge = bridge->bus->self)) { + pin = (pin + PCI_SLOT(bridge->devfn)) % 4; + irq = acpi_pci_irq_lookup(0, bridge->bus->number, PCI_SLOT(bridge->devfn), pin); + }; + + if (!irq) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to derive IRQ for device %s\n", dev->slot_name)); + return_VALUE(0); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derived IRQ %d\n", irq)); + + return_VALUE(irq); +} + + +int +acpi_pci_irq_enable ( + struct pci_dev *dev) +{ + int irq = 0; + u8 pin = 0; + static u16 irq_mask = 0; + + ACPI_FUNCTION_TRACE("acpi_pci_irq_enable"); + + if (!dev) + return_VALUE(-EINVAL); + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + if (!pin) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No interrupt pin configured for device %s\n", dev->slot_name)); + return_VALUE(0); + } + pin--; + + if (!dev->bus) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) 'bus' field\n")); + return_VALUE(-ENODEV); + } + + /* + * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT + * values override any BIOS-assinged IRQs set during boot. + */ + irq = acpi_pci_irq_lookup(0, dev->bus->number, PCI_SLOT(dev->devfn), pin); + + /* + * If no PRT entry was found, we'll try to derive an IRQ from the + * device's parent bridge. + */ + if (!irq) + irq = acpi_pci_irq_derive(dev, pin); + + if (irq) + dev->irq = irq; + + if (!dev->irq) { + printk(KERN_WARNING PREFIX "No IRQ known for interrupt pin %c of device %s\n", ('A' + pin), dev->slot_name); + return_VALUE(0); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s using IRQ %d\n", dev->slot_name, dev->irq)); + + /* + * Make sure all (legacy) PCI IRQs are set as level-triggered. + */ +#ifdef CONFIG_X86 + if ((dev->irq < 16) && !((1 << dev->irq) & irq_mask)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Setting IRQ %d as level-triggered\n", dev->irq)); + irq_mask |= (1 << dev->irq); + eisa_set_level_irq(dev->irq); + } +#endif + + return_VALUE(dev->irq); +} + + +int __init +acpi_pci_irq_init (void) +{ + struct pci_dev *dev = NULL; + + ACPI_FUNCTION_TRACE("acpi_pci_irq_init"); + + if (!acpi_prt.count) { + printk(KERN_WARNING PREFIX "ACPI tables contain no PCI IRQ " + "routing entries\n"); + return_VALUE(-ENODEV); + } + + /* Make sure all link devices have a valid IRQ. */ + acpi_pci_link_check(); + +#ifdef CONFIG_X86_IO_APIC + /* Program IOAPICs using data from PRT entries. */ + if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) + mp_parse_prt(); +#endif + + pci_for_each_dev(dev) + acpi_pci_irq_enable(dev); + + return_VALUE(0); +} diff -Nru a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/pci_link.c Sun Jun 2 18:44:56 2002 @@ -0,0 +1,581 @@ +/* + * pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 31 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * Copyright (C) 2002 Dominik Brodowski + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * TBD: + * 1. Support more than one IRQ resource entry per link device (index). + * 2. Implement start/stop mechanism and use ACPI Bus Driver facilities + * for IRQ management (e.g. start()->_SRS). + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_PCI_COMPONENT +ACPI_MODULE_NAME ("pci_link") + +#define PREFIX "ACPI: " + + +#define ACPI_PCI_LINK_MAX_POSSIBLE 16 + +static int acpi_pci_link_add (struct acpi_device *device); +static int acpi_pci_link_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_pci_link_driver = { + name: ACPI_PCI_LINK_DRIVER_NAME, + class: ACPI_PCI_LINK_CLASS, + ids: ACPI_PCI_LINK_HID, + ops: { + add: acpi_pci_link_add, + remove: acpi_pci_link_remove, + }, +}; + +struct acpi_pci_link_irq { + u8 active; /* Current IRQ */ + u8 possible_count; + u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; +}; + +struct acpi_pci_link { + struct list_head node; + struct acpi_device *device; + acpi_handle handle; + struct acpi_pci_link_irq irq; +}; + +static struct { + int count; + struct list_head entries; +} acpi_link; + + +/* -------------------------------------------------------------------------- + PCI Link Device Management + -------------------------------------------------------------------------- */ + +static int +acpi_pci_link_get_possible ( + struct acpi_pci_link *link) +{ + int result = 0; + acpi_status status = AE_OK; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_resource *resource = NULL; + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_pci_link_get_possible"); + + if (!link) + return_VALUE(-EINVAL); + + status = acpi_get_possible_resources(link->handle, &buffer); + if (ACPI_FAILURE(status) || !buffer.pointer) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n")); + result = -ENODEV; + goto end; + } + + resource = (acpi_resource *) buffer.pointer; + + switch (resource->id) { + case ACPI_RSTYPE_IRQ: + { + acpi_resource_irq *p = &resource->data.irq; + if (!p || !p->number_of_interrupts) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Blank IRQ resource\n")); + result = -ENODEV; + goto end; + } + for (i = 0; (inumber_of_interrupts && iinterrupts[i]) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i])); + continue; + } + link->irq.possible[i] = p->interrupts[i]; + link->irq.possible_count++; + } + break; + } + case ACPI_RSTYPE_EXT_IRQ: + { + acpi_resource_ext_irq *p = &resource->data.extended_irq; + if (!p || !p->number_of_interrupts) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, + "Blank IRQ resource\n")); + result = -ENODEV; + goto end; + } + for (i = 0; (inumber_of_interrupts && iinterrupts[i]) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i])); + continue; + } + link->irq.possible[i] = p->interrupts[i]; + link->irq.possible_count++; + } + break; + } + default: + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Resource is not an IRQ entry\n")); + result = -ENODEV; + goto end; + break; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Found %d possible IRQs\n", link->irq.possible_count)); + +end: + kfree(buffer.pointer); + + return_VALUE(result); +} + + +static int +acpi_pci_link_get_current ( + struct acpi_pci_link *link) +{ + int result = 0; + acpi_status status = AE_OK; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_resource *resource = NULL; + int irq = 0; + + ACPI_FUNCTION_TRACE("acpi_pci_link_get_current"); + + if (!link || !link->handle) + return_VALUE(-EINVAL); + + link->irq.active = 0; + + /* Make sure the link is enabled (no use querying if it isn't). */ + result = acpi_bus_get_status(link->device); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n")); + goto end; + } + if (!link->device->status.enabled) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link disabled\n")); + return_VALUE(0); + } + + /* + * Query and parse _CRS to get the current IRQ assignment. + */ + + status = acpi_get_current_resources(link->handle, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n")); + result = -ENODEV; + goto end; + } + resource = (acpi_resource *) buffer.pointer; + + switch (resource->id) { + case ACPI_RSTYPE_IRQ: + { + acpi_resource_irq *p = &resource->data.irq; + if (!p || !p->number_of_interrupts) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, + "Blank IRQ resource\n")); + result = -ENODEV; + goto end; + } + irq = p->interrupts[0]; + break; + } + case ACPI_RSTYPE_EXT_IRQ: + { + acpi_resource_ext_irq *p = &resource->data.extended_irq; + if (!p || !p->number_of_interrupts) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, + "Blank IRQ resource\n")); + result = -ENODEV; + goto end; + } + irq = p->interrupts[0]; + break; + } + default: + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Resource isn't an IRQ\n")); + result = -ENODEV; + goto end; + } + + if (!irq) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid use of IRQ 0\n")); + result = -ENODEV; + goto end; + } + + /* + * Note that we don't validate that the current IRQ (_CRS) exists + * within the possible IRQs (_PRS): we blindly assume that whatever + * IRQ a boot-enabled Link device is set to is the correct one. + * (Required to support systems such as the Toshiba 5005-S504.) + */ + + link->irq.active = irq; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active)); + +end: + kfree(buffer.pointer); + + return_VALUE(result); +} + + +static int +acpi_pci_link_set ( + struct acpi_pci_link *link, + int irq) +{ + int result = 0; + acpi_status status = AE_OK; + struct { + acpi_resource res; + acpi_resource end; + } resource; + acpi_buffer buffer = {sizeof(resource)+1, &resource}; + int i = 0; + int valid = 0; + + ACPI_FUNCTION_TRACE("acpi_pci_link_set"); + + if (!link || !irq) + return_VALUE(-EINVAL); + + /* See if we're already at the target IRQ. */ + if (irq == link->irq.active) + return_VALUE(0); + + /* Make sure the target IRQ in the list of possible IRQs. */ + for (i=0; iirq.possible_count; i++) { + if (irq == link->irq.possible[i]) + valid = 1; + } + if (!valid) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Target IRQ %d invalid\n", irq)); + return_VALUE(-EINVAL); + } + + memset(&resource, 0, sizeof(resource)); + + /* NOTE: PCI interrupts are always level / active_low / shared. */ + resource.res.id = ACPI_RSTYPE_IRQ; + resource.res.length = sizeof(acpi_resource); + resource.res.data.irq.edge_level = ACPI_LEVEL_SENSITIVE; + resource.res.data.irq.active_high_low = ACPI_ACTIVE_LOW; + resource.res.data.irq.shared_exclusive = ACPI_SHARED; + resource.res.data.irq.number_of_interrupts = 1; + resource.res.data.irq.interrupts[0] = irq; + resource.end.id = ACPI_RSTYPE_END_TAG; + + status = acpi_set_current_resources(link->handle, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n")); + return_VALUE(-ENODEV); + } + + /* Make sure the device is enabled. */ + result = acpi_bus_get_status(link->device); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n")); + return_VALUE(result); + } + if (!link->device->status.enabled) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link disabled\n")); + return_VALUE(-ENODEV); + } + + /* Make sure the active IRQ is the one we requested. */ + result = acpi_pci_link_get_current(link); + if (result) { + return_VALUE(result); + } + if (link->irq.active != irq) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Attempt to enable at IRQ %d resulted in IRQ %d\n", + irq, link->irq.active)); + link->irq.active = 0; + return_VALUE(-ENODEV); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", link->irq.active)); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + PCI Link IRQ Management + -------------------------------------------------------------------------- */ + +#define ACPI_MAX_IRQS 256 +#define ACPI_MAX_ISA_IRQ 16 + +/* + * IRQ penalties are used to promote PCI IRQ balancing. We set each ISA- + * possible IRQ (0-15) with a default penalty relative to its feasibility + * for PCI's use: + * + * Never use: 0, 1, 2 (timer, keyboard, and cascade) + * Avoid using: 13, 14, and 15 (FP error and IDE) + * Penalize: 3, 4, 6, 7, 12 (known ISA uses) + * + * Thus we're left with IRQs 5, 9, 10, 11, and everything above 15 (IO[S]APIC) + * as 'best bets' for PCI use. + */ + +static int acpi_irq_penalty[ACPI_MAX_IRQS] = { + 1000000, 1000000, 1000000, 10000, + 10000, 0, 10000, 10000, + 10000, 0, 0, 0, + 10000, 100000, 100000, 100000, +}; + + +int +acpi_pci_link_check (void) +{ + struct list_head *node = NULL; + struct acpi_pci_link *link = NULL; + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_pci_link_check"); + + /* + * Pass #1: Update penalties to facilitate IRQ balancing. + */ + list_for_each(node, &acpi_link.entries) { + + link = list_entry(node, struct acpi_pci_link, node); + if (!link) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); + continue; + } + + if (link->irq.active) + acpi_irq_penalty[link->irq.active] += 100; + else { + int penalty = 100 / link->irq.possible_count; + for (i=0; iirq.possible_count; i++) { + if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) + acpi_irq_penalty[link->irq.possible[i]] += penalty; + } + } + } + + /* + * Pass #2: Enable boot-disabled Links at 'best' IRQ. + */ + list_for_each(node, &acpi_link.entries) { + int irq = 0; + int i = 0; + + link = list_entry(node, struct acpi_pci_link, node); + if (!link) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); + continue; + } + + if (link->irq.active) + continue; + + irq = link->irq.possible[0]; + + /* + * Select the best IRQ. This is done in reverse to promote + * the use of IRQs 9, 10, 11, and >15. + */ + for (i=(link->irq.possible_count-1); i>0; i--) { + if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]]) + irq = link->irq.possible[i]; + } + + /* Enable the link device at this IRQ. */ + acpi_pci_link_set(link, irq); + + acpi_irq_penalty[link->irq.active] += 100; + + printk(PREFIX "%s [%s] enabled at IRQ %d\n", + acpi_device_name(link->device), + acpi_device_bid(link->device), irq); + } + + return_VALUE(0); +} + + +int +acpi_pci_link_get_irq ( + acpi_handle handle, + int index) +{ + int result = 0; + struct acpi_device *device = NULL; + struct acpi_pci_link *link = NULL; + + ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq"); + + result = acpi_bus_get_device(handle, &device); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n")); + return_VALUE(0); + } + + link = (struct acpi_pci_link *) acpi_driver_data(device); + if (!link) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); + return_VALUE(0); + } + + /* TBD: Support multiple index (IRQ) entries per Link Device */ + if (index) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid index %d\n", index)); + return_VALUE(0); + } + + if (!link->irq.active) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link disabled\n")); + return_VALUE(0); + } + + return_VALUE(link->irq.active); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +static int +acpi_pci_link_add ( + struct acpi_device *device) +{ + int result = 0; + struct acpi_pci_link *link = NULL; + int i = 0; + int found = 0; + + ACPI_FUNCTION_TRACE("acpi_pci_link_add"); + + if (!device) + return_VALUE(-EINVAL); + + link = kmalloc(sizeof(struct acpi_pci_link), GFP_KERNEL); + if (!link) + return_VALUE(-ENOMEM); + memset(link, 0, sizeof(struct acpi_pci_link)); + + link->device = device; + link->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_PCI_LINK_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_PCI_LINK_CLASS); + acpi_driver_data(device) = link; + + result = acpi_pci_link_get_possible(link); + if (result) + goto end; + + acpi_pci_link_get_current(link); + + printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device), acpi_device_bid(device)); + for (i = 0; i < link->irq.possible_count; i++) { + if (link->irq.active == link->irq.possible[i]) { + printk(" *%d", link->irq.possible[i]); + found = 1; + } + else + printk(" %d", link->irq.possible[i]); + } + if (!link->irq.active) + printk(", disabled"); + else if (!found) + printk(", enabled at IRQ %d", link->irq.active); + printk(")\n"); + + /* TBD: Acquire/release lock */ + list_add_tail(&link->node, &acpi_link.entries); + acpi_link.count++; + +end: + if (result) + kfree(link); + + return_VALUE(result); +} + + +static int +acpi_pci_link_remove ( + struct acpi_device *device, + int type) +{ + struct acpi_pci_link *link = NULL; + + ACPI_FUNCTION_TRACE("acpi_pci_link_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + link = (struct acpi_pci_link *) acpi_driver_data(device); + + /* TBD: Acquire/release lock */ + list_del(&link->node); + + kfree(link); + + return_VALUE(0); +} + + +int __init +acpi_pci_link_init (void) +{ + ACPI_FUNCTION_TRACE("acpi_pci_link_init"); + + acpi_link.count = 0; + INIT_LIST_HEAD(&acpi_link.entries); + + if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0) + return_VALUE(-ENODEV); + + return_VALUE(0); +} diff -Nru a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/pci_root.c Sun Jun 2 18:44:56 2002 @@ -0,0 +1,246 @@ +/* + * pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 37 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_PCI_COMPONENT +ACPI_MODULE_NAME ("pci_root") + +extern struct pci_ops *pci_root_ops; + +#define PREFIX "ACPI: " + +static int acpi_pci_root_add (struct acpi_device *device); +static int acpi_pci_root_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_pci_root_driver = { + name: ACPI_PCI_ROOT_DRIVER_NAME, + class: ACPI_PCI_ROOT_CLASS, + ids: ACPI_PCI_ROOT_HID, + ops: { + add: acpi_pci_root_add, + remove: acpi_pci_root_remove, + }, +}; + +struct acpi_pci_root { + acpi_handle handle; + acpi_pci_id id; + struct pci_bus *bus; +}; + + +static int +acpi_pci_root_add ( + struct acpi_device *device) +{ + int result = 0; + struct acpi_pci_root *root = NULL; + acpi_status status = AE_OK; + unsigned long value = 0; + acpi_handle handle = NULL; + + ACPI_FUNCTION_TRACE("acpi_pci_root_add"); + + if (!device) + return_VALUE(-EINVAL); + + root = kmalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); + if (!root) + return_VALUE(-ENOMEM); + memset(root, 0, sizeof(struct acpi_pci_root)); + + root->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_PCI_ROOT_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_PCI_ROOT_CLASS); + acpi_driver_data(device) = root; + + /* + * TBD: Doesn't the bus driver automatically set this? + */ + device->ops.bind = acpi_pci_bind; + + /* + * Segment + * ------- + * Obtained via _SEG, if exists, otherwise assumed to be zero (0). + */ + status = acpi_evaluate_integer(root->handle, METHOD_NAME__SEG, NULL, + &value); + switch (status) { + case AE_OK: + root->id.segment = (u16) value; + printk("_SEG exists! Unsupported. Abort.\n"); + BUG(); + break; + case AE_NOT_FOUND: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Assuming segment 0 (no _SEG)\n")); + root->id.segment = 0; + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SEG\n")); + result = -ENODEV; + goto end; + } + + /* + * Bus + * --- + * Obtained via _BBN, if exists, otherwise assumed to be zero (0). + */ + status = acpi_evaluate_integer(root->handle, METHOD_NAME__BBN, NULL, + &value); + switch (status) { + case AE_OK: + root->id.bus = (u16) value; + break; + case AE_NOT_FOUND: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming bus 0 (no _BBN)\n")); + root->id.bus = 0; + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BBN\n")); + result = -ENODEV; + goto end; + } + + /* + * Device & Function + * ----------------- + * Obtained from _ADR (which has already been evaluated for us). + */ + root->id.device = device->pnp.bus_address >> 16; + root->id.function = device->pnp.bus_address & 0xFFFF; + + /* + * TBD: Evaluate _CRS to get root bridge resources + * TBD: Need PCI interface for enumeration/configuration of roots. + */ + + printk(KERN_INFO PREFIX "%s [%s] (%02x:%02x)\n", + acpi_device_name(device), acpi_device_bid(device), + root->id.segment, root->id.bus); + + /* + * Scan the Root Bridge + * -------------------- + * Must do this prior to any attempt to bind the root device, as the + * PCI namespace does not get created until this call is made (and + * thus the root bridge's pci_dev does not exist). + */ + root->bus = pcibios_scan_root(root->id.bus); + if (!root->bus) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Bus %02x:%02x not present in PCI namespace\n", + root->id.segment, root->id.bus)); + result = -ENODEV; + goto end; + } + + /* + * Attach ACPI-PCI Context + * ----------------------- + * Thus binding the ACPI and PCI devices. + */ + result = acpi_pci_bind_root(device, &root->id, root->bus); + if (result) + goto end; + + /* + * PCI Routing Table + * ----------------- + * Evaluate and parse _PRT, if exists. + */ + status = acpi_get_handle(root->handle, METHOD_NAME__PRT, &handle); + if (ACPI_SUCCESS(status)) + result = acpi_pci_irq_add_prt(root->handle, root->id.segment, + root->id.bus); + +end: + if (result) + kfree(root); + + return_VALUE(result); +} + + +static int +acpi_pci_root_remove ( + struct acpi_device *device, + int type) +{ + struct acpi_pci_root *root = NULL; + + ACPI_FUNCTION_TRACE("acpi_pci_root_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + root = (struct acpi_pci_root *) acpi_driver_data(device); + + kfree(root); + + return_VALUE(0); +} + + +int __init +acpi_pci_root_init (void) +{ + ACPI_FUNCTION_TRACE("acpi_pci_root_init"); + + /* DEBUG: + acpi_dbg_layer = ACPI_PCI_COMPONENT; + acpi_dbg_level = 0xFFFFFFFF; + */ + + if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + + +void __exit +acpi_pci_root_exit (void) +{ + ACPI_FUNCTION_TRACE("acpi_pci_root_exit"); + + acpi_bus_unregister_driver(&acpi_pci_root_driver); + + return_VOID; +} diff -Nru a/drivers/acpi/power.c b/drivers/acpi/power.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/power.c Sun Jun 2 18:44:56 2002 @@ -0,0 +1,609 @@ +/* + * acpi_power.c - ACPI Bus Power Management ($Revision: 37 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_POWER_COMPONENT +ACPI_MODULE_NAME ("acpi_power") + +#define PREFIX "ACPI: " + + +int acpi_power_add (struct acpi_device *device); +int acpi_power_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_power_driver = { + name: ACPI_POWER_DRIVER_NAME, + class: ACPI_POWER_CLASS, + ids: ACPI_POWER_HID, + ops: { + add: acpi_power_add, + remove: acpi_power_remove, + }, +}; + +struct acpi_power_resource +{ + acpi_handle handle; + acpi_bus_id name; + u32 system_level; + u32 order; + int state; + int references; +}; + +static struct list_head acpi_power_resource_list; + + +/* -------------------------------------------------------------------------- + Power Resource Management + -------------------------------------------------------------------------- */ + +static int +acpi_power_get_context ( + acpi_handle handle, + struct acpi_power_resource **resource) +{ + int result = 0; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_power_get_context"); + + if (!resource) + return_VALUE(-ENODEV); + + result = acpi_bus_get_device(handle, &device); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error getting context [%p]\n", + handle)); + return_VALUE(result); + } + + *resource = (struct acpi_power_resource *) acpi_driver_data(device); + if (!resource) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + + +static int +acpi_power_get_state ( + struct acpi_power_resource *resource) +{ + acpi_status status = AE_OK; + unsigned long sta = 0; + + ACPI_FUNCTION_TRACE("acpi_power_get_state"); + + if (!resource) + return_VALUE(-EINVAL); + + status = acpi_evaluate_integer(resource->handle, "_STA", NULL, &sta); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + if (sta & 0x01) + resource->state = ACPI_POWER_RESOURCE_STATE_ON; + else + resource->state = ACPI_POWER_RESOURCE_STATE_OFF; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", + resource->name, resource->state?"on":"off")); + + return_VALUE(0); +} + + +static int +acpi_power_get_list_state ( + struct acpi_handle_list *list, + int *state) +{ + int result = 0; + struct acpi_power_resource *resource = NULL; + u32 i = 0; + + ACPI_FUNCTION_TRACE("acpi_power_get_list_state"); + + if (!list || !state) + return_VALUE(-EINVAL); + + /* The state of the list is 'on' IFF all resources are 'on'. */ + + for (i=0; icount; i++) { + result = acpi_power_get_context(list->handles[i], &resource); + if (result) + return_VALUE(result); + result = acpi_power_get_state(resource); + if (result) + return_VALUE(result); + + *state = resource->state; + + if (*state != ACPI_POWER_RESOURCE_STATE_ON) + break; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n", + *state?"on":"off")); + + return_VALUE(result); +} + + +static int +acpi_power_on ( + acpi_handle handle) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_device *device = NULL; + struct acpi_power_resource *resource = NULL; + + ACPI_FUNCTION_TRACE("acpi_power_on"); + + result = acpi_power_get_context(handle, &resource); + if (result) + return_VALUE(result); + + resource->references++; + + if ((resource->references > 1) + || (resource->state == ACPI_POWER_RESOURCE_STATE_ON)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n", + resource->name)); + return_VALUE(0); + } + + status = acpi_evaluate(resource->handle, "_ON", NULL, NULL); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + result = acpi_power_get_state(resource); + if (result) + return_VALUE(result); + if (resource->state != ACPI_POWER_RESOURCE_STATE_ON) + return_VALUE(-ENOEXEC); + + /* Update the power resource's _device_ power state */ + result = acpi_bus_get_device(resource->handle, &device); + if (result) + return_VALUE(result); + device->power.state = ACPI_STATE_D0; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n", + resource->name)); + + return_VALUE(0); +} + + +static int +acpi_power_off ( + acpi_handle handle) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_device *device = NULL; + struct acpi_power_resource *resource = NULL; + + ACPI_FUNCTION_TRACE("acpi_power_off"); + + result = acpi_power_get_context(handle, &resource); + if (result) + return_VALUE(result); + + if (resource->references) + resource->references--; + + if (resource->references) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Resource [%s] is still in use, dereferencing\n", + device->pnp.bus_id)); + return_VALUE(0); + } + + if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n", + device->pnp.bus_id)); + return_VALUE(0); + } + + status = acpi_evaluate(resource->handle, "_OFF", NULL, NULL); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + result = acpi_power_get_state(resource); + if (result) + return_VALUE(result); + if (resource->state != ACPI_POWER_RESOURCE_STATE_OFF) + return_VALUE(-ENOEXEC); + + /* Update the power resource's _device_ power state */ + result = acpi_bus_get_device(resource->handle, &device); + if (result) + return_VALUE(result); + device->power.state = ACPI_STATE_D3; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n", + resource->name)); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Device Power Management + -------------------------------------------------------------------------- */ + +int +acpi_power_get_inferred_state ( + struct acpi_device *device) +{ + int result = 0; + struct acpi_handle_list *list = NULL; + int list_state = 0; + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_power_get_inferred_state"); + + if (!device) + return_VALUE(-EINVAL); + + device->power.state = ACPI_STATE_UNKNOWN; + + /* + * We know a device's inferred power state when all the resources + * required for a given D-state are 'on'. + */ + for (i=ACPI_STATE_D0; ipower.states[i].resources; + if (list->count < 1) + continue; + + result = acpi_power_get_list_state(list, &list_state); + if (result) + return_VALUE(result); + + if (list_state == ACPI_POWER_RESOURCE_STATE_ON) { + device->power.state = i; + return_VALUE(0); + } + } + + device->power.state = ACPI_STATE_D3; + + return_VALUE(0); +} + + +int +acpi_power_transition ( + struct acpi_device *device, + int state) +{ + int result = 0; + struct acpi_handle_list *cl = NULL; /* Current Resources */ + struct acpi_handle_list *tl = NULL; /* Target Resources */ + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_power_transition"); + + if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) + return_VALUE(-EINVAL); + + cl = &device->power.states[device->power.state].resources; + tl = &device->power.states[state].resources; + + device->power.state = ACPI_STATE_UNKNOWN; + + if (!cl->count && !tl->count) { + result = -ENODEV; + goto end; + } + + /* TBD: Resources must be ordered. */ + + /* + * First we reference all power resources required in the target list + * (e.g. so the device doesn't loose power while transitioning). + */ + for (i=0; icount; i++) { + result = acpi_power_on(tl->handles[i]); + if (result) + goto end; + } + + device->power.state = state; + + /* + * Then we dereference all power resources used in the current list. + */ + for (i=0; icount; i++) { + result = acpi_power_off(cl->handles[i]); + if (result) + goto end; + } + +end: + if (result) + ACPI_DEBUG_PRINT((ACPI_DB_WARN, + "Error transitioning device [%s] to D%d\n", + device->pnp.bus_id, state)); + + return_VALUE(result); +} + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +struct proc_dir_entry *acpi_power_dir = NULL; + + +static int +acpi_power_read_status ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_power_resource *resource = NULL; + char *p = page; + int len; + + ACPI_FUNCTION_TRACE("acpi_power_read_status"); + + if (!data || (off != 0)) + goto end; + + resource = (struct acpi_power_resource *) data; + + p += sprintf(p, "state: "); + switch (resource->state) { + case ACPI_POWER_RESOURCE_STATE_ON: + p += sprintf(p, "on\n"); + break; + case ACPI_POWER_RESOURCE_STATE_OFF: + p += sprintf(p, "off\n"); + break; + default: + p += sprintf(p, "unknown\n"); + break; + } + + p += sprintf(p, "system level: S%d\n", + resource->system_level); + p += sprintf(p, "order: %d\n", + resource->order); + p += sprintf(p, "reference count: %d\n", + resource->references); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_power_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_power_add_fs"); + + if (!device) + return_VALUE(-EINVAL); + + if (!acpi_power_dir) { + acpi_power_dir = proc_mkdir(ACPI_POWER_CLASS, acpi_root_dir); + if (!acpi_power_dir) + return_VALUE(-ENODEV); + } + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_power_dir); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + } + + /* 'status' [R] */ + entry = create_proc_entry(ACPI_POWER_FILE_STATUS, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_POWER_FILE_STATUS)); + else { + entry->read_proc = acpi_power_read_status; + entry->data = acpi_driver_data(device); + } + + return_VALUE(0); +} + + +static int +acpi_power_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_power_remove_fs"); + + if (!acpi_power_dir) + return_VALUE(-ENODEV); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_power_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +int +acpi_power_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_power_resource *resource = NULL; + acpi_object acpi_object; + acpi_buffer buffer = {sizeof(acpi_object), &acpi_object}; + + ACPI_FUNCTION_TRACE("acpi_power_add"); + + if (!device) + return_VALUE(-EINVAL); + + resource = kmalloc(sizeof(struct acpi_power_resource), GFP_KERNEL); + if (!resource) + return_VALUE(-ENOMEM); + memset(resource, 0, sizeof(struct acpi_power_resource)); + + resource->handle = device->handle; + sprintf(resource->name, "%s", device->pnp.bus_id); + sprintf(acpi_device_name(device), "%s", ACPI_POWER_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_POWER_CLASS); + acpi_driver_data(device) = resource; + + /* Evalute the object to get the system level and resource order. */ + status = acpi_evaluate_object(resource->handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) { + result = -ENODEV; + goto end; + } + resource->system_level = acpi_object.power_resource.system_level; + resource->order = acpi_object.power_resource.resource_order; + + result = acpi_power_get_state(resource); + if (result) + goto end; + + switch (resource->state) { + case ACPI_POWER_RESOURCE_STATE_ON: + device->power.state = ACPI_STATE_D0; + break; + case ACPI_POWER_RESOURCE_STATE_OFF: + device->power.state = ACPI_STATE_D3; + break; + default: + device->power.state = ACPI_STATE_UNKNOWN; + break; + } + + result = acpi_power_add_fs(device); + if (result) + goto end; + + printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), + acpi_device_bid(device), resource->state?"on":"off"); + +end: + if (result) + kfree(resource); + + return_VALUE(result); +} + + +int +acpi_power_remove ( + struct acpi_device *device, + int type) +{ + struct acpi_power_resource *resource = NULL; + + ACPI_FUNCTION_TRACE("acpi_power_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + resource = (struct acpi_power_resource *) acpi_driver_data(device); + + acpi_power_remove_fs(device); + + kfree(resource); + + return_VALUE(0); +} + + +int __init +acpi_power_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_power_init"); + + INIT_LIST_HEAD(&acpi_power_resource_list); + + result = acpi_bus_register_driver(&acpi_power_driver); + if (result < 0) { + remove_proc_entry(ACPI_POWER_CLASS, acpi_root_dir); + return_VALUE(-ENODEV); + } + + return_VALUE(0); +} + + +void __exit +acpi_power_exit (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_power_exit"); + + /* TBD: Empty acpi_power_resource_list */ + + result = acpi_bus_unregister_driver(&acpi_power_driver); + if (!result) + remove_proc_entry(ACPI_POWER_CLASS, acpi_root_dir); + + return_VOID; +} diff -Nru a/drivers/acpi/processor.c b/drivers/acpi/processor.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/processor.c Sun Jun 2 18:44:58 2002 @@ -0,0 +1,2314 @@ +/* + * acpi_processor.c - ACPI Processor Driver ($Revision: 66 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * TBD: + * 1. Make # power/performance states dynamic. + * 2. Support duty_cycle values that span bit 4. + * 3. Optimize by having scheduler determine business instead of + * having us try to calculate it here. + * 4. Need C1 timing -- must modify kernel (IRQ handler) to get this. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_PROCESSOR_COMPONENT +ACPI_MODULE_NAME ("acpi_processor") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define PREFIX "ACPI: " + +#define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000) +#define C2_OVERHEAD 4 /* 1us (3.579 ticks per us) */ +#define C3_OVERHEAD 4 /* 1us (3.579 ticks per us) */ + +#define ACPI_PROCESSOR_BUSY_METRIC 10 + +#define ACPI_PROCESSOR_MAX_POWER ACPI_C_STATE_COUNT +#define ACPI_PROCESSOR_MAX_C2_LATENCY 100 +#define ACPI_PROCESSOR_MAX_C3_LATENCY 1000 + +#define ACPI_PROCESSOR_MAX_PERFORMANCE 8 + +#define ACPI_PROCESSOR_MAX_THROTTLING 16 +#define ACPI_PROCESSOR_MAX_THROTTLE 250 /* 25% */ +#define ACPI_PROCESSOR_MAX_DUTY_WIDTH 4 + +const u32 POWER_OF_2[] = {1,2,4,8,16,32,64}; + +#define ACPI_PROCESSOR_LIMIT_USER 0 +#define ACPI_PROCESSOR_LIMIT_THERMAL 1 + +static int acpi_processor_add (struct acpi_device *device); +static int acpi_processor_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_processor_driver = { + name: ACPI_PROCESSOR_DRIVER_NAME, + class: ACPI_PROCESSOR_CLASS, + ids: ACPI_PROCESSOR_HID, + ops: { + add: acpi_processor_add, + remove: acpi_processor_remove, + }, +}; + +/* Power Management */ + +struct acpi_processor_cx_policy { + u32 count; + int state; + struct { + u32 time; + u32 ticks; + u32 count; + u32 bm; + } threshold; +}; + +struct acpi_processor_cx { + u8 valid; + u32 address; + u32 latency; + u32 latency_ticks; + u32 power; + u32 usage; + struct acpi_processor_cx_policy promotion; + struct acpi_processor_cx_policy demotion; +}; + +struct acpi_processor_power { + int state; + int default_state; + u32 bm_activity; + struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER]; +}; + +/* Performance Management */ + +struct acpi_pct_register { + u8 descriptor; + u16 length; + u8 space_id; + u8 bit_width; + u8 bit_offset; + u8 reserved; + u64 address; +} __attribute__ ((packed)); + +struct acpi_processor_px { + acpi_integer core_frequency; /* megahertz */ + acpi_integer power; /* milliWatts */ + acpi_integer transition_latency; /* microseconds */ + acpi_integer bus_master_latency; /* microseconds */ + acpi_integer control; /* control value */ + acpi_integer status; /* success indicator */ +}; + +struct acpi_processor_performance { + int state; + int platform_limit; + u16 control_register; + u16 status_register; + int state_count; + struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE]; +}; + + +/* Throttling Control */ + +struct acpi_processor_tx { + u16 power; + u16 performance; +}; + +struct acpi_processor_throttling { + int state; + u32 address; + u8 duty_offset; + u8 duty_width; + int state_count; + struct acpi_processor_tx states[ACPI_PROCESSOR_MAX_THROTTLING]; +}; + +/* Limit Interface */ + +struct acpi_processor_lx { + int px; /* performace state */ + int tx; /* throttle level */ +}; + +struct acpi_processor_limit { + struct acpi_processor_lx state; /* current limit */ + struct acpi_processor_lx thermal; /* thermal limit */ + struct acpi_processor_lx user; /* user limit */ +}; + + +struct acpi_processor_flags { + u8 power:1; + u8 performance:1; + u8 throttling:1; + u8 limit:1; + u8 bm_control:1; + u8 bm_check:1; + u8 reserved:2; +}; + +struct acpi_processor { + acpi_handle handle; + u32 acpi_id; + u32 id; + struct acpi_processor_flags flags; + struct acpi_processor_power power; + struct acpi_processor_performance performance; + struct acpi_processor_throttling throttling; + struct acpi_processor_limit limit; +}; + +struct acpi_processor_errata { + u8 smp; + struct { + u8 throttle:1; + u8 fdma:1; + u8 reserved:6; + u32 bmisx; + } piix4; +}; + +static struct acpi_processor *processors[NR_CPUS]; +static struct acpi_processor_errata errata; +static void (*pm_idle_save)(void) = NULL; + + +/* -------------------------------------------------------------------------- + Errata Handling + -------------------------------------------------------------------------- */ + +int +acpi_processor_errata_piix4 ( + struct pci_dev *dev) +{ + u8 rev = 0; + u8 value1 = 0; + u8 value2 = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_errata_piix4"); + + if (!dev) + return_VALUE(-EINVAL); + + /* + * Note that 'dev' references the PIIX4 ACPI Controller. + */ + + pci_read_config_byte(dev, PCI_REVISION_ID, &rev); + + switch (rev) { + case 0: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n")); + break; + case 1: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n")); + break; + case 2: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n")); + break; + case 3: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n")); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n")); + break; + } + + switch (rev) { + + case 0: /* PIIX4 A-step */ + case 1: /* PIIX4 B-step */ + /* + * See specification changes #13 ("Manual Throttle Duty Cycle") + * and #14 ("Enabling and Disabling Manual Throttle"), plus + * erratum #5 ("STPCLK# Deassertion Time") from the January + * 2002 PIIX4 specification update. Applies to only older + * PIIX4 models. + */ + errata.piix4.throttle = 1; + + case 2: /* PIIX4E */ + case 3: /* PIIX4M */ + /* + * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA + * Livelock") from the January 2002 PIIX4 specification update. + * Applies to all PIIX4 models. + */ + + /* + * BM-IDE + * ------ + * Find the PIIX4 IDE Controller and get the Bus Master IDE + * Status register address. We'll use this later to read + * each IDE controller's DMA status to make sure we catch all + * DMA activity. + */ + dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB, + PCI_ANY_ID, PCI_ANY_ID, NULL); + if (dev) + errata.piix4.bmisx = pci_resource_start(dev, 4); + + /* + * Type-F DMA + * ---------- + * Find the PIIX4 ISA Controller and read the Motherboard + * DMA controller's status to see if Type-F (Fast) DMA mode + * is enabled (bit 7) on either channel. Note that we'll + * disable C3 support if this is enabled, as some legacy + * devices won't operate well if fast DMA is disabled. + */ + dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_0, + PCI_ANY_ID, PCI_ANY_ID, NULL); + if (dev) { + pci_read_config_byte(dev, 0x76, &value1); + pci_read_config_byte(dev, 0x77, &value2); + if ((value1 & 0x80) || (value2 & 0x80)) + errata.piix4.fdma = 1; + } + + break; + } + + if (errata.piix4.bmisx) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Bus master activity detection (BM-IDE) erratum enabled\n")); + if (errata.piix4.fdma) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Type-F DMA livelock erratum (C3 disabled)\n")); + + return_VALUE(0); +} + + +int +acpi_processor_errata ( + struct acpi_processor *pr) +{ + int result = 0; + struct pci_dev *dev = NULL; + + ACPI_FUNCTION_TRACE("acpi_processor_errata"); + + if (!pr) + return_VALUE(-EINVAL); + + /* + * PIIX4 + */ + dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, NULL); + if (dev) + result = acpi_processor_errata_piix4(dev); + + return_VALUE(result); +} + + +/* -------------------------------------------------------------------------- + Power Management + -------------------------------------------------------------------------- */ + +static inline u32 +ticks_elapsed ( + u32 t1, + u32 t2) +{ + if (t2 >= t1) + return (t2 - t1); + else if (!acpi_fadt.tmr_val_ext) + return (((0x00FFFFFF - t1) + t2) & 0x00FFFFFF); + else + return ((0xFFFFFFFF - t1) + t2); +} + + +static void +acpi_processor_power_activate ( + struct acpi_processor *pr, + int state) +{ + if (!pr) + return; + + pr->power.states[pr->power.state].promotion.count = 0; + pr->power.states[pr->power.state].demotion.count = 0; + + /* Cleanup from old state. */ + switch (pr->power.state) { + case ACPI_STATE_C3: + /* Disable bus master reload */ + acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, ACPI_MTX_DO_NOT_LOCK); + break; + } + + /* Prepare to use new state. */ + switch (state) { + case ACPI_STATE_C3: + /* Enable bus master reload */ + acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1, ACPI_MTX_DO_NOT_LOCK); + break; + } + + pr->power.state = state; + + return; +} + + +static void +acpi_processor_idle (void) +{ + struct acpi_processor *pr = NULL; + struct acpi_processor_cx *cx = NULL; + int next_state = 0; + int sleep_ticks = 0; + u32 t1, t2 = 0; + + pr = processors[smp_processor_id()]; + if (!pr) + return; + + /* + * Interrupts must be disabled during bus mastering calculations and + * for C2/C3 transitions. + */ + __cli(); + + cx = &(pr->power.states[pr->power.state]); + + /* + * Check BM Activity + * ----------------- + * Check for bus mastering activity (if required), record, and check + * for demotion. + */ + if (pr->flags.bm_check) { + u32 bm_status = 0; + + pr->power.bm_activity <<= 1; + + acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, + &bm_status, ACPI_MTX_DO_NOT_LOCK); + if (bm_status) { + pr->power.bm_activity++; + acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, + 1, ACPI_MTX_DO_NOT_LOCK); + } + /* + * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect + * the true state of bus mastering activity; forcing us to + * manually check the BMIDEA bit of each IDE channel. + */ + else if (errata.piix4.bmisx) { + if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01) + || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01)) + pr->power.bm_activity++; + } + /* + * Apply bus mastering demotion policy. Automatically demote + * to avoid a faulty transition. Note that the processor + * won't enter a low-power state during this call (to this + * funciton) but should upon the next. + * + * TBD: A better policy might be to fallback to the demotion + * state (use it for this quantum only) istead of + * demoting -- and rely on duration as our sole demotion + * qualification. This may, however, introduce DMA + * issues (e.g. floppy DMA transfer overrun/underrun). + */ + if (pr->power.bm_activity & cx->demotion.threshold.bm) { + __sti(); + next_state = cx->demotion.state; + goto end; + } + } + + cx->usage++; + + /* + * Sleep: + * ------ + * Invoke the current Cx state to put the processor to sleep. + */ + switch (pr->power.state) { + + case ACPI_STATE_C1: + /* Invoke C1. */ + safe_halt(); + /* + * TBD: Can't get time duration while in C1, as resumes + * go to an ISR rather than here. Need to instrument + * base interrupt handler. + */ + sleep_ticks = 0xFFFFFFFF; + break; + + case ACPI_STATE_C2: + /* Get start time (ticks) */ + t1 = inl(acpi_fadt.Xpm_tmr_blk.address); + /* Invoke C2 */ + inb(pr->power.states[ACPI_STATE_C2].address); + /* Dummy op - must do something useless after P_LVL2 read */ + t2 = inl(acpi_fadt.Xpm_tmr_blk.address); + /* Get end time (ticks) */ + t2 = inl(acpi_fadt.Xpm_tmr_blk.address); + /* Re-enable interrupts */ + __sti(); + /* Compute time (ticks) that we were actually asleep */ + sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD; + break; + + case ACPI_STATE_C3: + /* Disable bus master arbitration */ + acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK); + /* Get start time (ticks) */ + t1 = inl(acpi_fadt.Xpm_tmr_blk.address); + /* Invoke C3 */ + inb(pr->power.states[ACPI_STATE_C3].address); + /* Dummy op - must do something useless after P_LVL3 read */ + t2 = inl(acpi_fadt.Xpm_tmr_blk.address); + /* Get end time (ticks) */ + t2 = inl(acpi_fadt.Xpm_tmr_blk.address); + /* Enable bus master arbitration */ + acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK); + /* Re-enable interrupts */ + __sti(); + /* Compute time (ticks) that we were actually asleep */ + sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD; + break; + + default: + __sti(); + return; + } + + next_state = pr->power.state; + + /* + * Promotion? + * ---------- + * Track the number of longs (time asleep is greater than threshold) + * and promote when the count threshold is reached. Note that bus + * mastering activity may prevent promotions. + */ + if (cx->promotion.state) { + if (sleep_ticks > cx->promotion.threshold.ticks) { + cx->promotion.count++; + cx->demotion.count = 0; + if (cx->promotion.count >= cx->promotion.threshold.count) { + if (pr->flags.bm_check) { + if (!(pr->power.bm_activity & cx->promotion.threshold.bm)) { + next_state = cx->promotion.state; + goto end; + } + } + else { + next_state = cx->promotion.state; + goto end; + } + } + } + } + + /* + * Demotion? + * --------- + * Track the number of shorts (time asleep is less than time threshold) + * and demote when the usage threshold is reached. + */ + if (cx->demotion.state) { + if (sleep_ticks < cx->demotion.threshold.ticks) { + cx->demotion.count++; + cx->promotion.count = 0; + if (cx->demotion.count >= cx->demotion.threshold.count) { + next_state = cx->demotion.state; + goto end; + } + } + } + +end: + /* + * New Cx State? + * ------------- + * If we're going to start using a new Cx state we must clean up + * from the previous and prepare to use the new. + */ + if (next_state != pr->power.state) + acpi_processor_power_activate(pr, next_state); + + return; +} + + +static int +acpi_processor_set_power_policy ( + struct acpi_processor *pr) +{ + ACPI_FUNCTION_TRACE("acpi_processor_set_power_policy"); + + /* + * This function sets the default Cx state policy (OS idle handler). + * Our scheme is to promote quickly to C2 but more conservatively + * to C3. We're favoring C2 for its characteristics of low latency + * (quick response), good power savings, and ability to allow bus + * mastering activity. Note that the Cx state policy is completely + * customizable and can be altered dynamically. + */ + + if (!pr) + return_VALUE(-EINVAL); + + /* + * C0/C1 + * ----- + */ + pr->power.state = ACPI_STATE_C1; + pr->power.default_state = ACPI_STATE_C1; + + /* + * C1/C2 + * ----- + * Set the default C1 promotion and C2 demotion policies, where we + * promote from C1 to C2 after several (10) successive C1 transitions, + * as we cannot (currently) measure the time spent in C1. Demote from + * C2 to C1 after experiencing several (4) 'shorts' (time spent in C2 + * is less than the C2 transtion latency). + */ + if (pr->power.states[ACPI_STATE_C2].valid) { + pr->power.states[ACPI_STATE_C1].promotion.threshold.count = 10; + pr->power.states[ACPI_STATE_C1].promotion.threshold.ticks = + pr->power.states[ACPI_STATE_C2].latency_ticks; + pr->power.states[ACPI_STATE_C1].promotion.state = ACPI_STATE_C2; + + pr->power.states[ACPI_STATE_C2].demotion.threshold.count = 4; + pr->power.states[ACPI_STATE_C2].demotion.threshold.ticks = + pr->power.states[ACPI_STATE_C2].latency_ticks; + pr->power.states[ACPI_STATE_C2].demotion.state = ACPI_STATE_C1; + } + + /* + * C2/C3 + * ----- + * Set default C2 promotion and C3 demotion policies, where we promote + * from C2 to C3 after several (4) cycles of no bus mastering activity + * while maintaining sleep time criteria. Demote immediately on a + * short or whenever bus mastering activity occurs. + */ + if ((pr->power.states[ACPI_STATE_C2].valid) && + (pr->power.states[ACPI_STATE_C3].valid)) { + pr->power.states[ACPI_STATE_C2].promotion.threshold.count = 4; + pr->power.states[ACPI_STATE_C2].promotion.threshold.ticks = + pr->power.states[ACPI_STATE_C3].latency_ticks; + pr->power.states[ACPI_STATE_C2].promotion.threshold.bm = 0x0F; + pr->power.states[ACPI_STATE_C2].promotion.state = ACPI_STATE_C3; + + pr->power.states[ACPI_STATE_C3].demotion.threshold.count = 1; + pr->power.states[ACPI_STATE_C3].demotion.threshold.ticks = + pr->power.states[ACPI_STATE_C3].latency_ticks; + pr->power.states[ACPI_STATE_C3].demotion.threshold.bm = 0x0F; + pr->power.states[ACPI_STATE_C3].demotion.state = ACPI_STATE_C2; + } + + return_VALUE(0); +} + + +int +acpi_processor_get_power_info ( + struct acpi_processor *pr) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_get_power_info"); + + if (!pr) + return_VALUE(-EINVAL); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "lvl2[0x%08x] lvl3[0x%08x]\n", + pr->power.states[ACPI_STATE_C2].address, + pr->power.states[ACPI_STATE_C3].address)); + + /* TBD: Support ACPI 2.0 objects */ + + /* + * C0 + * -- + * This state exists only as filler in our array. + */ + pr->power.states[ACPI_STATE_C0].valid = 1; + + /* + * C1 + * -- + * ACPI requires C1 support for all processors. + * + * TBD: What about PROC_C1? + */ + pr->power.states[ACPI_STATE_C1].valid = 1; + + /* + * C2 + * -- + * We're (currently) only supporting C2 on UP systems. + * + * TBD: Support for C2 on MP (P_LVL2_UP). + */ + if (pr->power.states[ACPI_STATE_C2].address) { + + pr->power.states[ACPI_STATE_C2].latency = acpi_fadt.plvl2_lat; + + /* + * C2 latency must be less than or equal to 100 microseconds. + */ + if (acpi_fadt.plvl2_lat >= ACPI_PROCESSOR_MAX_C2_LATENCY) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "C2 latency too large [%d]\n", + acpi_fadt.plvl2_lat)); + /* + * Only support C2 on UP systems (see TBD above). + */ + else if (errata.smp) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "C2 not supported in SMP mode\n")); + /* + * Otherwise we've met all of our C2 requirements. + * Normalize the C2 latency to expidite policy. + */ + else { + pr->power.states[ACPI_STATE_C2].valid = 1; + pr->power.states[ACPI_STATE_C2].latency_ticks = + US_TO_PM_TIMER_TICKS(acpi_fadt.plvl2_lat); + } + } + + /* + * C3 + * -- + * TBD: Investigate use of WBINVD on UP/SMP system in absence of + * bm_control. + */ + if (pr->power.states[ACPI_STATE_C3].address) { + + pr->power.states[ACPI_STATE_C3].latency = acpi_fadt.plvl3_lat; + + /* + * C3 latency must be less than or equal to 1000 microseconds. + */ + if (acpi_fadt.plvl3_lat >= ACPI_PROCESSOR_MAX_C3_LATENCY) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "C3 latency too large [%d]\n", + acpi_fadt.plvl3_lat)); + /* + * Only support C3 when bus mastering arbitration control + * is present (able to disable bus mastering to maintain + * cache coherency while in C3). + */ + else if (!pr->flags.bm_control) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "C3 support requires bus mastering control\n")); + /* + * Only support C3 on UP systems, as bm_control is only viable + * on a UP system and flushing caches (e.g. WBINVD) is simply + * too costly (at this time). + */ + else if (errata.smp) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "C3 not supported in SMP mode\n")); + /* + * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) + * DMA transfers are used by any ISA device to avoid livelock. + * Note that we could disable Type-F DMA (as recommended by + * the erratum), but this is known to disrupt certain ISA + * devices thus we take the conservative approach. + */ + else if (errata.piix4.fdma) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "C3 not supported on PIIX4 with Type-F DMA\n")); + } + /* + * Otherwise we've met all of our C3 requirements. + * Normalize the C2 latency to expidite policy. Enable + * checking of bus mastering status (bm_check) so we can + * use this in our C3 policy. + */ + else { + pr->power.states[ACPI_STATE_C3].valid = 1; + pr->power.states[ACPI_STATE_C3].latency_ticks = + US_TO_PM_TIMER_TICKS(acpi_fadt.plvl3_lat); + pr->flags.bm_check = 1; + } + } + + /* + * Set Default Policy + * ------------------ + * Now that we know which state are supported, set the default + * policy. Note that this policy can be changed dynamically + * (e.g. encourage deeper sleeps to conserve battery life when + * not on AC). + */ + result = acpi_processor_set_power_policy(pr); + if (result) + return_VALUE(result); + + /* + * If this processor supports C2 or C3 we denote it as being 'power + * manageable'. Note that there's really no policy involved for + * when only C1 is supported. + */ + if (pr->power.states[ACPI_STATE_C2].valid + || pr->power.states[ACPI_STATE_C3].valid) + pr->flags.power = 1; + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Performance Management + -------------------------------------------------------------------------- */ + +static int +acpi_processor_get_platform_limit ( + struct acpi_processor* pr) +{ + acpi_status status = 0; + unsigned long ppc = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_get_platform_limit"); + + if (!pr) + return_VALUE(-EINVAL); + + /* + * _PPC indicates the maximum state currently supported by the platform + * (e.g. 0 = states 0..n; 1 = states 1..n; etc. + */ + status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc); + if(ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PPC\n")); + return_VALUE(-ENODEV); + } + + pr->performance.platform_limit = (int) ppc; + + return_VALUE(0); +} + + +static int +acpi_processor_get_performance_control ( + struct acpi_processor *pr) +{ + int result = 0; + acpi_status status = 0; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_object *pct = NULL; + acpi_object obj = {0}; + struct acpi_pct_register *reg = NULL; + + ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control"); + + status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer); + if(ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PCT\n")); + return_VALUE(-ENODEV); + } + + pct = (acpi_object *) buffer.pointer; + if (!pct || (pct->type != ACPI_TYPE_PACKAGE) + || (pct->package.count != 2)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PCT data\n")); + result = -EFAULT; + goto end; + } + + /* + * control_register + */ + + obj = pct->package.elements[0]; + + if ((obj.type != ACPI_TYPE_BUFFER) + || (obj.buffer.length < sizeof(struct acpi_pct_register)) + || (obj.buffer.pointer == NULL)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Invalid _PCT data (control_register)\n")); + result = -EFAULT; + goto end; + } + + reg = (struct acpi_pct_register *) (obj.buffer.pointer); + + if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unsupported address space [%d] (control_register)\n", + (u32) reg->space_id)); + result = -EFAULT; + goto end; + } + + pr->performance.control_register = (u16) reg->address; + + /* + * status_register + */ + + obj = pct->package.elements[1]; + + if ((obj.type != ACPI_TYPE_BUFFER) + || (obj.buffer.length < sizeof(struct acpi_pct_register)) + || (obj.buffer.pointer == NULL)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Invalid _PCT data (status_register)\n")); + result = -EFAULT; + goto end; + } + + reg = (struct acpi_pct_register *) (obj.buffer.pointer); + + if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unsupported address space [%d] (status_register)\n", + (u32) reg->space_id)); + result = -EFAULT; + goto end; + } + + pr->performance.status_register = (u16) reg->address; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "control_register[0x%04x] status_register[0x%04x]\n", + pr->performance.control_register, + pr->performance.status_register)); + +end: + kfree(buffer.pointer); + + return_VALUE(result); +} + + +static int +acpi_processor_get_performance_states ( + struct acpi_processor* pr) +{ + int result = 0; + acpi_status status = AE_OK; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_buffer format = {sizeof("NNNNNN"), "NNNNNN"}; + acpi_buffer state = {0, NULL}; + acpi_object *pss = NULL; + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states"); + + status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer); + if(ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PSS\n")); + return_VALUE(-ENODEV); + } + + pss = (acpi_object *) buffer.pointer; + if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n")); + result = -EFAULT; + goto end; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n", + pss->package.count)); + + if (pss->package.count > ACPI_PROCESSOR_MAX_PERFORMANCE) { + pr->performance.state_count = ACPI_PROCESSOR_MAX_PERFORMANCE; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Limiting number of states to max (%d)\n", + ACPI_PROCESSOR_MAX_PERFORMANCE)); + } + else + pr->performance.state_count = pss->package.count; + + if (pr->performance.state_count > 1) + pr->flags.performance = 1; + + for (i = 0; i < pr->performance.state_count; i++) { + + struct acpi_processor_px *px = &(pr->performance.states[i]); + + state.length = sizeof(struct acpi_processor_px); + state.pointer = px; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i)); + + status = acpi_extract_package(&(pss->package.elements[i]), + &format, &state); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n")); + result = -EFAULT; + goto end; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n", + i, + (u32) px->core_frequency, + (u32) px->power, + (u32) px->transition_latency, + (u32) px->bus_master_latency, + (u32) px->control, + (u32) px->status)); + } + +end: + kfree(buffer.pointer); + + return_VALUE(result); +} + + +static int +acpi_processor_set_performance ( + struct acpi_processor *pr, + int state) +{ + u16 port = 0; + u8 value = 0; + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_set_performance"); + + if (!pr) + return_VALUE(-EINVAL); + + if (!pr->flags.performance) + return_VALUE(-ENODEV); + + if (state >= pr->performance.state_count) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, + "Invalid target state (P%d)\n", state)); + return_VALUE(-ENODEV); + } + + if (state < pr->performance.platform_limit) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, + "Platform limit (P%d) overrides target state (P%d)\n", + pr->performance.platform_limit, state)); + return_VALUE(-ENODEV); + } + + if (state == pr->performance.state) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Already at target state (P%d)\n", state)); + return_VALUE(0); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Transitioning from P%d to P%d\n", + pr->performance.state, state)); + + /* + * First we write the target state's 'control' value to the + * control_register. + */ + + port = pr->performance.control_register; + value = (u16) pr->performance.states[state].control; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Writing 0x%02x to port 0x%04x\n", value, port)); + + outb(value, port); + + /* + * Then we read the 'status_register' and compare the value with the + * target state's 'status' to make sure the transition was successful. + * Note that we'll poll for up to 1ms (100 cycles of 10us) before + * giving up. + */ + + port = pr->performance.status_register; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Looking for 0x%02x from port 0x%04x\n", + (u8) pr->performance.states[state].status, port)); + + for (i=0; i<100; i++) { + value = inb(port); + if (value == (u8) pr->performance.states[state].status) + break; + udelay(10); + } + + if (value != pr->performance.states[state].status) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n")); + return_VALUE(-ENODEV); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Transition successful after %d microseconds\n", + i * 10)); + + pr->performance.state = state; + + return_VALUE(0); +} + + +static int +acpi_processor_get_performance_info ( + struct acpi_processor *pr) +{ + int result = 0; + acpi_status status = AE_OK; + acpi_handle handle = NULL; + + ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info"); + + if (!pr) + return_VALUE(-EINVAL); + + status = acpi_get_handle(pr->handle, "_PCT", &handle); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "ACPI-based processor performance control unavailable\n")); + return_VALUE(0); + } + + result = acpi_processor_get_performance_control(pr); + if (result) + return_VALUE(result); + + result = acpi_processor_get_performance_states(pr); + if (result) + return_VALUE(result); + + result = acpi_processor_get_platform_limit(pr); + if (result) + return_VALUE(result); + + /* + * TBD: Don't trust the latency values we get from BIOS, but rather + * measure the latencies during run-time (e.g. get_latencies). + */ + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Throttling Control + -------------------------------------------------------------------------- */ + +static int +acpi_processor_get_throttling ( + struct acpi_processor *pr) +{ + int state = 0; + u32 value = 0; + u32 duty_mask = 0; + u32 duty_value = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_get_throttling"); + + if (!pr) + return_VALUE(-EINVAL); + + if (!pr->flags.throttling) + return_VALUE(-ENODEV); + + pr->throttling.state = 0; + + __cli(); + + duty_mask = pr->throttling.state_count - 1; + + duty_mask <<= pr->throttling.duty_offset; + + value = inl(pr->throttling.address); + + /* + * Compute the current throttling state when throttling is enabled + * (bit 4 is on). + */ + if (value & 0x10) { + duty_value = value & duty_mask; + duty_value >>= pr->throttling.duty_offset; + + if (duty_value) + state = pr->throttling.state_count-duty_value; + } + + pr->throttling.state = state; + + __sti(); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Throttling state is T%d (%d%% throttling applied)\n", + state, pr->throttling.states[state].performance)); + + return_VALUE(0); +} + + +static int +acpi_processor_set_throttling ( + struct acpi_processor *pr, + int state) +{ + u32 value = 0; + u32 duty_mask = 0; + u32 duty_value = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_set_throttling"); + + if (!pr) + return_VALUE(-EINVAL); + + if ((state < 0) || (state > (pr->throttling.state_count - 1))) + return_VALUE(-EINVAL); + + if (!pr->flags.throttling) + return_VALUE(-ENODEV); + + if (state == pr->throttling.state) + return_VALUE(0); + + __cli(); + + /* + * Calculate the duty_value and duty_mask. + */ + if (state) { + duty_value = pr->throttling.state_count - state; + + duty_value <<= pr->throttling.duty_offset; + + /* Used to clear all duty_value bits */ + duty_mask = pr->throttling.state_count - 1; + + duty_mask <<= acpi_fadt.duty_offset; + duty_mask = ~duty_mask; + } + + /* + * Disable throttling by writing a 0 to bit 4. Note that we must + * turn it off before you can change the duty_value. + */ + value = inl(pr->throttling.address); + if (value & 0x10) { + value &= 0xFFFFFFEF; + outl(value, pr->throttling.address); + } + + /* + * Write the new duty_value and then enable throttling. Note + * that a state value of 0 leaves throttling disabled. + */ + if (state) { + value &= duty_mask; + value |= duty_value; + outl(value, pr->throttling.address); + + value |= 0x00000010; + outl(value, pr->throttling.address); + } + + pr->throttling.state = state; + + __sti(); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Throttling state set to T%d (%d%%)\n", state, + (pr->throttling.states[state].performance?pr->throttling.states[state].performance/10:0))); + + return_VALUE(0); +} + + +static int +acpi_processor_get_throttling_info ( + struct acpi_processor *pr) +{ + int result = 0; + int step = 0; + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_get_throttling_info"); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", + pr->throttling.address, + pr->throttling.duty_offset, + pr->throttling.duty_width)); + + if (!pr) + return_VALUE(-EINVAL); + + /* TBD: Support ACPI 2.0 objects */ + + if (!pr->throttling.address) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); + return_VALUE(0); + } + else if (!pr->throttling.duty_width) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n")); + return_VALUE(0); + } + /* TBD: Support duty_cycle values that span bit 4. */ + else if ((pr->throttling.duty_offset + + pr->throttling.duty_width) > 4) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "duty_cycle spans bit 4\n")); + return_VALUE(0); + } + + /* + * PIIX4 Errata: We don't support throttling on the original PIIX4. + * This shouldn't be an issue as few (if any) mobile systems ever + * used this part. + */ + if (errata.piix4.throttle) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Throttling not supported on PIIX4 A- or B-step\n")); + return_VALUE(0); + } + + pr->throttling.state_count = POWER_OF_2[acpi_fadt.duty_width]; + + /* + * Compute state values. Note that throttling displays a linear power/ + * performance relationship (at 50% performance the CPU will consume + * 50% power). Values are in 1/10th of a percent to preserve accuracy. + */ + + step = (1000 / pr->throttling.state_count); + + for (i=0; ithrottling.state_count; i++) { + pr->throttling.states[i].performance = step * i; + pr->throttling.states[i].power = step * i; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n", + pr->throttling.state_count)); + + pr->flags.throttling = 1; + + /* + * Disable throttling (if enabled). We'll let subsequent policy (e.g. + * thermal) decide to lower performance if it so chooses, but for now + * we'll crank up the speed. + */ + + result = acpi_processor_get_throttling(pr); + if (result) + goto end; + + if (pr->throttling.state) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabling throttling (was T%d)\n", + pr->throttling.state)); + result = acpi_processor_set_throttling(pr, 0); + if (result) + goto end; + } + +end: + if (result) + pr->flags.throttling = 0; + + return_VALUE(result); +} + + +/* -------------------------------------------------------------------------- + Limit Interface + -------------------------------------------------------------------------- */ + +static int +acpi_processor_apply_limit ( + struct acpi_processor* pr) +{ + int result = 0; + u16 px = 0; + u16 tx = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_apply_limit"); + + if (!pr) + return_VALUE(-EINVAL); + + if (!pr->flags.limit) + return_VALUE(-ENODEV); + + if (pr->flags.performance) { + px = pr->performance.platform_limit; + if (pr->limit.user.px > px) + px = pr->limit.user.px; + if (pr->limit.thermal.px > px) + px = pr->limit.thermal.px; + + result = acpi_processor_set_performance(pr, px); + if (result) + goto end; + } + + if (pr->flags.throttling) { + if (pr->limit.user.tx > tx) + tx = pr->limit.user.tx; + if (pr->limit.thermal.tx > tx) + tx = pr->limit.thermal.tx; + + result = acpi_processor_set_throttling(pr, tx); + if (result) + goto end; + } + + pr->limit.state.px = px; + pr->limit.state.tx = tx; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d] limit set to (P%d:T%d)\n", + pr->id, + pr->limit.state.px, + pr->limit.state.tx)); + +end: + if (result) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to set limit\n")); + + return_VALUE(result); +} + + +int +acpi_processor_set_thermal_limit ( + acpi_handle handle, + int type) +{ + int result = 0; + struct acpi_processor *pr = NULL; + struct acpi_device *device = NULL; + int px = 0; + int tx = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit"); + + if ((type < ACPI_PROCESSOR_LIMIT_NONE) + || (type > ACPI_PROCESSOR_LIMIT_DECREMENT)) + return_VALUE(-EINVAL); + + result = acpi_bus_get_device(handle, &device); + if (result) + return_VALUE(result); + + pr = (struct acpi_processor *) acpi_driver_data(device); + if (!pr) + return_VALUE(-ENODEV); + + if (!pr->flags.limit) + return_VALUE(-ENODEV); + + /* Thermal limits are always relative to the current Px/Tx state. */ + if (pr->flags.performance) + pr->limit.thermal.px = pr->performance.state; + if (pr->flags.throttling) + pr->limit.thermal.tx = pr->throttling.state; + + /* + * Our default policy is to only use throttling at the lowest + * performance state. + */ + + switch (type) { + + case ACPI_PROCESSOR_LIMIT_NONE: + px = 0; + tx = 0; + break; + + case ACPI_PROCESSOR_LIMIT_INCREMENT: + if (pr->flags.performance) { + if (px == (pr->performance.state_count - 1)) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "At maximum performance state\n")); + else { + px++; + goto end; + } + } + if (pr->flags.throttling) { + if (tx == (pr->throttling.state_count - 1)) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "At maximum throttling state\n")); + else + tx++; + } + break; + + case ACPI_PROCESSOR_LIMIT_DECREMENT: + if (pr->flags.performance) { + if (px == pr->performance.platform_limit) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "At minimum performance state\n")); + else { + px--; + goto end; + } + } + if (pr->flags.throttling) { + if (tx == 0) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "At minimum throttling state\n")); + else + tx--; + } + break; + } + +end: + pr->limit.thermal.px = px; + pr->limit.thermal.tx = tx; + + result = acpi_processor_apply_limit(pr); + if (result) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to set thermal limit\n")); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n", + pr->limit.thermal.px, + pr->limit.thermal.tx)); + + return_VALUE(result); +} + + +static int +acpi_processor_get_limit_info ( + struct acpi_processor *pr) +{ + ACPI_FUNCTION_TRACE("acpi_processor_get_limit_info"); + + if (!pr) + return_VALUE(-EINVAL); + + if (pr->flags.performance || pr->flags.throttling) + pr->flags.limit = 1; + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +struct proc_dir_entry *acpi_processor_dir = NULL; + +static int +acpi_processor_read_info ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_processor *pr = (struct acpi_processor *) data; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_read_info"); + + if (!pr || (off != 0)) + goto end; + + p += sprintf(p, "processor id: %d\n", + pr->id); + + p += sprintf(p, "acpi id: %d\n", + pr->acpi_id); + + p += sprintf(p, "bus mastering control: %s\n", + pr->flags.bm_control ? "yes" : "no"); + + p += sprintf(p, "power management: %s\n", + pr->flags.power ? "yes" : "no"); + + p += sprintf(p, "throttling control: %s\n", + pr->flags.throttling ? "yes" : "no"); + + p += sprintf(p, "performance management: %s\n", + pr->flags.performance ? "yes" : "no"); + + p += sprintf(p, "limit interface: %s\n", + pr->flags.limit ? "yes" : "no"); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_processor_read_power ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_processor *pr = (struct acpi_processor *) data; + char *p = page; + int len = 0; + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_read_power"); + + if (!pr || (off != 0)) + goto end; + + p += sprintf(p, "active state: C%d\n", + pr->power.state); + + p += sprintf(p, "default state: C%d\n", + pr->power.default_state); + + p += sprintf(p, "bus master activity: %08x\n", + pr->power.bm_activity); + + p += sprintf(p, "states:\n"); + + for (i=1; ipower.state?'*':' '), i); + + if (!pr->power.states[i].valid) { + p += sprintf(p, "\n"); + continue; + } + + if (pr->power.states[i].promotion.state) + p += sprintf(p, "promotion[C%d] ", + pr->power.states[i].promotion.state); + else + p += sprintf(p, "promotion[--] "); + + if (pr->power.states[i].demotion.state) + p += sprintf(p, "demotion[C%d] ", + pr->power.states[i].demotion.state); + else + p += sprintf(p, "demotion[--] "); + + p += sprintf(p, "latency[%03d] usage[%08d]\n", + pr->power.states[i].latency, + pr->power.states[i].usage); + } + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_processor_read_performance ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_processor *pr = (struct acpi_processor *) data; + char *p = page; + int len = 0; + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_read_performance"); + + if (!pr || (off != 0)) + goto end; + + if (!pr->flags.performance) { + p += sprintf(p, "\n"); + goto end; + } + + p += sprintf(p, "state count: %d\n", + pr->performance.state_count); + + p += sprintf(p, "active state: P%d\n", + pr->performance.state); + + p += sprintf(p, "states:\n"); + + for (i=0; iperformance.state_count; i++) + p += sprintf(p, " %cP%d: %d MHz, %d mW, %d uS\n", + (i == pr->performance.state?'*':' '), i, + (u32) pr->performance.states[i].core_frequency, + (u32) pr->performance.states[i].power, + (u32) pr->performance.states[i].transition_latency); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_processor_write_performance ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + struct acpi_processor *pr = (struct acpi_processor *) data; + char state_string[12] = {'\0'}; + + ACPI_FUNCTION_TRACE("acpi_processor_write_performance"); + + if (!pr || (count > sizeof(state_string) - 1)) + return_VALUE(-EINVAL); + + if (copy_from_user(state_string, buffer, count)) + return_VALUE(-EFAULT); + + state_string[count] = '\0'; + + result = acpi_processor_set_performance(pr, + simple_strtoul(state_string, NULL, 0)); + if (result) + return_VALUE(result); + + return_VALUE(count); +} + + +static int +acpi_processor_read_throttling ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_processor *pr = (struct acpi_processor *) data; + char *p = page; + int len = 0; + int i = 0; + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_read_throttling"); + + if (!pr || (off != 0)) + goto end; + + if (!(pr->throttling.state_count > 0)) { + p += sprintf(p, "\n"); + goto end; + } + + result = acpi_processor_get_throttling(pr); + + if (result) { + p += sprintf(p, "Could not determine current throttling state.\n"); + goto end; + } + + p += sprintf(p, "state count: %d\n", + pr->throttling.state_count); + + p += sprintf(p, "active state: T%d\n", + pr->throttling.state); + + p += sprintf(p, "states:\n"); + + for (i=0; ithrottling.state_count; i++) + p += sprintf(p, " %cT%d: %02d%%\n", + (i == pr->throttling.state?'*':' '), i, + (pr->throttling.states[i].performance?pr->throttling.states[i].performance/10:0)); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_processor_write_throttling ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + struct acpi_processor *pr = (struct acpi_processor *) data; + char state_string[12] = {'\0'}; + + ACPI_FUNCTION_TRACE("acpi_processor_write_throttling"); + + if (!pr || (count > sizeof(state_string) - 1)) + return_VALUE(-EINVAL); + + if (copy_from_user(state_string, buffer, count)) + return_VALUE(-EFAULT); + + state_string[count] = '\0'; + + result = acpi_processor_set_throttling(pr, + simple_strtoul(state_string, NULL, 0)); + if (result) + return_VALUE(result); + + return_VALUE(count); +} + + +static int +acpi_processor_read_limit ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_processor *pr = (struct acpi_processor *) data; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_read_limit"); + + if (!pr || (off != 0)) + goto end; + + if (!pr->flags.limit) { + p += sprintf(p, "\n"); + goto end; + } + + p += sprintf(p, "active limit: P%d:T%d\n", + pr->limit.state.px, pr->limit.state.tx); + + p += sprintf(p, "platform limit: P%d:T0\n", + pr->flags.performance?pr->performance.platform_limit:0); + + p += sprintf(p, "user limit: P%d:T%d\n", + pr->limit.user.px, pr->limit.user.tx); + + p += sprintf(p, "thermal limit: P%d:T%d\n", + pr->limit.thermal.px, pr->limit.thermal.tx); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_processor_write_limit ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + struct acpi_processor *pr = (struct acpi_processor *) data; + char limit_string[25] = {'\0'}; + int px = 0; + int tx = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_write_limit"); + + if (!pr || (count > sizeof(limit_string) - 1)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n")); + return_VALUE(-EINVAL); + } + + if (copy_from_user(limit_string, buffer, count)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n")); + return_VALUE(-EFAULT); + } + + limit_string[count] = '\0'; + + if (sscanf(limit_string, "%d:%d", &px, &tx) != 2) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n")); + return_VALUE(-EINVAL); + } + + if (pr->flags.performance) { + if ((px < pr->performance.platform_limit) + || (px > (pr->performance.state_count - 1))) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid px\n")); + return_VALUE(-EINVAL); + } + pr->limit.user.px = px; + } + + if (pr->flags.throttling) { + if ((tx < 0) || (tx > (pr->throttling.state_count - 1))) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid tx\n")); + return_VALUE(-EINVAL); + } + pr->limit.user.tx = tx; + } + + result = acpi_processor_apply_limit(pr); + + return_VALUE(count); +} + + +static int +acpi_processor_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_processor_add_fs"); + + if (!acpi_processor_dir) { + acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, + acpi_root_dir); + if (!acpi_processor_dir) + return_VALUE(-ENODEV); + } + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_processor_dir); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + } + + /* 'info' [R] */ + entry = create_proc_entry(ACPI_PROCESSOR_FILE_INFO, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_PROCESSOR_FILE_INFO)); + else { + entry->read_proc = acpi_processor_read_info; + entry->data = acpi_driver_data(device); + } + + /* 'power' [R] */ + entry = create_proc_entry(ACPI_PROCESSOR_FILE_POWER, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_PROCESSOR_FILE_POWER)); + else { + entry->read_proc = acpi_processor_read_power; + entry->data = acpi_driver_data(device); + } + + /* 'performance' [R/W] */ + entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_PROCESSOR_FILE_PERFORMANCE)); + else { + entry->read_proc = acpi_processor_read_performance; + entry->write_proc = acpi_processor_write_performance; + entry->data = acpi_driver_data(device); + } + + /* 'throttling' [R/W] */ + entry = create_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_PROCESSOR_FILE_THROTTLING)); + else { + entry->read_proc = acpi_processor_read_throttling; + entry->write_proc = acpi_processor_write_throttling; + entry->data = acpi_driver_data(device); + } + + /* 'limit' [R/W] */ + entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_PROCESSOR_FILE_LIMIT)); + else { + entry->read_proc = acpi_processor_read_limit; + entry->write_proc = acpi_processor_write_limit; + entry->data = acpi_driver_data(device); + } + + return_VALUE(0); +} + + +static int +acpi_processor_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_processor_remove_fs"); + + if (!acpi_processor_dir) + return_VALUE(-ENODEV); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_processor_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +static int +acpi_processor_get_info ( + struct acpi_processor *pr) +{ + acpi_status status = 0; + acpi_object object = {0}; + acpi_buffer buffer = {sizeof(acpi_object), &object}; + static int cpu_count = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_get_info"); + + if (!pr) + return_VALUE(-EINVAL); + +#ifdef CONFIG_SMP + if (smp_num_cpus > 1) + errata.smp = smp_num_cpus; +#endif + + acpi_processor_errata(pr); + + /* + * Check to see if we have bus mastering arbitration control. This + * is required for proper C3 usage (to maintain cache coherency). + */ + if (acpi_fadt.V1_pm2_cnt_blk && acpi_fadt.pm2_cnt_len) { + pr->flags.bm_control = 1; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Bus mastering arbitration control present\n")); + } + else + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "No bus mastering arbitration control\n")); + + /* + * Evalute the processor object. Note that it is common on SMP to + * have the first (boot) processor with a valid PBLK address while + * all others have a NULL address. + */ + status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error evaluating processor object\n")); + return_VALUE(-ENODEV); + } + + /* + * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. + * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c + */ + pr->id = cpu_count++; + pr->acpi_id = object.processor.proc_id; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, + pr->acpi_id)); + + if (!object.processor.pblk_address) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n")); + else if (object.processor.pblk_length < 6) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid PBLK length [%d]\n", + object.processor.pblk_length)); + else { + pr->throttling.address = object.processor.pblk_address; + pr->throttling.duty_offset = acpi_fadt.duty_offset; + pr->throttling.duty_width = acpi_fadt.duty_width; + pr->power.states[ACPI_STATE_C2].address = + object.processor.pblk_address + 4; + pr->power.states[ACPI_STATE_C3].address = + object.processor.pblk_address + 5; + } + + acpi_processor_get_power_info(pr); + acpi_processor_get_performance_info(pr); + acpi_processor_get_throttling_info(pr); + acpi_processor_get_limit_info(pr); + + return_VALUE(0); +} + + +static void +acpi_processor_notify ( + acpi_handle handle, + u32 event, + void *data) +{ + int result = 0; + struct acpi_processor *pr = (struct acpi_processor *) data; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_processor_notify"); + + if (!pr) + return_VOID; + + if (acpi_bus_get_device(pr->handle, &device)) + return_VOID; + + switch (event) { + case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: + result = acpi_processor_get_platform_limit(pr); + if (!result) + acpi_processor_apply_limit(pr); + + acpi_bus_generate_event(device, event, + pr->performance.platform_limit); + break; + case ACPI_PROCESSOR_NOTIFY_POWER: + /* TBD */ + acpi_bus_generate_event(device, event, 0); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return_VOID; +} + + +static int +acpi_processor_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_processor *pr = NULL; + u32 i = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_add"); + + if (!device) + return_VALUE(-EINVAL); + + pr = kmalloc(sizeof(struct acpi_processor), GFP_KERNEL); + if (!pr) + return_VALUE(-ENOMEM); + memset(pr, 0, sizeof(struct acpi_processor)); + + pr->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_PROCESSOR_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_PROCESSOR_CLASS); + acpi_driver_data(device) = pr; + + result = acpi_processor_get_info(pr); + if (result) + goto end; + + result = acpi_processor_add_fs(device); + if (result) + goto end; + + status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, + acpi_processor_notify, pr); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing notify handler\n")); + result = -ENODEV; + goto end; + } + + processors[pr->id] = pr; + + /* + * Install the idle handler if processor power management is supported. + * Note that the default idle handler (default_idle) will be used on + * platforms that only support C1. + */ + if ((pr->id == 0) && (pr->flags.power)) { + pm_idle_save = pm_idle; + pm_idle = acpi_processor_idle; + } + + printk(KERN_INFO PREFIX "%s [%s] (supports", + acpi_device_name(device), acpi_device_bid(device)); + for (i=1; ipower.states[i].valid) + printk(" C%d", i); + if (pr->flags.performance) + printk(", %d performance states", pr->performance.state_count); + if (pr->flags.throttling) + printk(", %d throttling states", pr->throttling.state_count); + printk(")\n"); + +end: + if (result) { + acpi_processor_remove_fs(device); + kfree(pr); + } + + return_VALUE(result); +} + + +static int +acpi_processor_remove ( + struct acpi_device *device, + int type) +{ + acpi_status status = AE_OK; + struct acpi_processor *pr = NULL; + + ACPI_FUNCTION_TRACE("acpi_processor_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + pr = (struct acpi_processor *) acpi_driver_data(device); + + /* Unregister the idle handler when processor #0 is removed. */ + if (pr->id == 0) + pm_idle = pm_idle_save; + + status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, + acpi_processor_notify); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + return_VALUE(-ENODEV); + } + + acpi_processor_remove_fs(device); + + processors[pr->id] = NULL; + + kfree(pr); + + return_VALUE(0); +} + + +static int __init +acpi_processor_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_init"); + + memset(&processors, 0, sizeof(processors)); + memset(&errata, 0, sizeof(errata)); + + result = acpi_bus_register_driver(&acpi_processor_driver); + if (result < 0) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + + +static void __exit +acpi_processor_exit (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_exit"); + + result = acpi_bus_unregister_driver(&acpi_processor_driver); + if (!result) + remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); + + return_VOID; +} + + +module_init(acpi_processor_init); +module_exit(acpi_processor_exit); diff -Nru a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c --- a/drivers/acpi/resources/rsaddr.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/resources/rsaddr.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rsaddr - Address resource descriptors (16/32/64) - * $Revision: 24 $ + * $Revision: 26 $ * ******************************************************************************/ @@ -60,8 +60,8 @@ ACPI_SIZE *structure_size) { u8 *buffer = byte_stream_buffer; - acpi_resource *output_struct = (acpi_resource *) *output_buffer; - NATIVE_CHAR *temp_ptr; + acpi_resource *output_struct = (void *) *output_buffer; + u8 *temp_ptr; ACPI_SIZE struct_size = ACPI_SIZEOF_RESOURCE (acpi_resource_address16); u32 index; u16 temp16; @@ -200,7 +200,7 @@ output_struct->data.address16.resource_source.string_ptr = (NATIVE_CHAR *)((u8 * )output_struct + struct_size); - temp_ptr = output_struct->data.address16.resource_source.string_ptr; + temp_ptr = (u8 *) output_struct->data.address16.resource_source.string_ptr; /* Copy the string into the buffer */ @@ -238,7 +238,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure @@ -390,8 +390,7 @@ * Buffer needs to be set to the length of the sting + one for the * terminating null */ - buffer += (ACPI_STRLEN (linked_list->data.address16.resource_source.string_ptr) - + 1); + buffer += (ACPI_STRLEN (linked_list->data.address16.resource_source.string_ptr) + 1); } /* @@ -439,10 +438,10 @@ ACPI_SIZE *structure_size) { u8 *buffer; - acpi_resource *output_struct; + acpi_resource *output_struct= (void *) *output_buffer; u16 temp16; u8 temp8; - NATIVE_CHAR *temp_ptr; + u8 *temp_ptr; ACPI_SIZE struct_size; u32 index; @@ -451,8 +450,6 @@ buffer = byte_stream_buffer; - output_struct = (acpi_resource *) *output_buffer; - struct_size = ACPI_SIZEOF_RESOURCE (acpi_resource_address32); /* @@ -588,7 +585,7 @@ output_struct->data.address32.resource_source.string_ptr = (NATIVE_CHAR *)((u8 *)output_struct + struct_size); - temp_ptr = output_struct->data.address32.resource_source.string_ptr; + temp_ptr = (u8 *) output_struct->data.address32.resource_source.string_ptr; /* Copy the string into the buffer */ @@ -624,7 +621,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure @@ -676,7 +673,7 @@ /* * Set a pointer to the Length field - to be filled in later */ - length_field = (u16 *) buffer; + length_field = ACPI_CAST_PTR (u16, buffer); buffer += 2; /* @@ -823,10 +820,10 @@ ACPI_SIZE *structure_size) { u8 *buffer; - acpi_resource *output_struct; + acpi_resource *output_struct = (void *) *output_buffer; u16 temp16; u8 temp8; - NATIVE_CHAR *temp_ptr; + u8 *temp_ptr; ACPI_SIZE struct_size; u32 index; @@ -835,8 +832,6 @@ buffer = byte_stream_buffer; - output_struct = (acpi_resource *) *output_buffer; - struct_size = ACPI_SIZEOF_RESOURCE (acpi_resource_address64); /* @@ -975,7 +970,7 @@ output_struct->data.address64.resource_source.string_ptr = (NATIVE_CHAR *)((u8 *)output_struct + struct_size); - temp_ptr = output_struct->data.address64.resource_source.string_ptr; + temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr; /* Copy the string into the buffer */ @@ -1012,7 +1007,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure @@ -1065,7 +1060,7 @@ * Set a pointer to the Length field - to be filled in later */ - length_field = (u16 *)buffer; + length_field = ACPI_CAST_PTR (u16, buffer); buffer += 2; /* diff -Nru a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c --- a/drivers/acpi/resources/rscalc.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/resources/rscalc.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rscalc - Calculate stream and list lengths - * $Revision: 39 $ + * $Revision: 42 $ * ******************************************************************************/ @@ -35,7 +35,7 @@ /******************************************************************************* * - * FUNCTION: Acpi_rs_calculate_byte_stream_length + * FUNCTION: Acpi_rs_get_byte_stream_length * * PARAMETERS: Linked_list - Pointer to the resource linked list * Size_needed - u32 pointer of the size buffer needed @@ -50,7 +50,7 @@ ******************************************************************************/ acpi_status -acpi_rs_calculate_byte_stream_length ( +acpi_rs_get_byte_stream_length ( acpi_resource *linked_list, ACPI_SIZE *size_needed) { @@ -60,7 +60,7 @@ u8 done = FALSE; - ACPI_FUNCTION_TRACE ("Rs_calculate_byte_stream_length"); + ACPI_FUNCTION_TRACE ("Rs_get_byte_stream_length"); while (!done) { @@ -180,9 +180,9 @@ */ segment_size = 16; - if (NULL != linked_list->data.address16.resource_source.string_ptr) { - segment_size += (1 + - linked_list->data.address16.resource_source.string_length); + if (linked_list->data.address16.resource_source.string_ptr) { + segment_size += linked_list->data.address16.resource_source.string_length; + segment_size++; } break; @@ -196,9 +196,9 @@ */ segment_size = 26; - if (NULL != linked_list->data.address32.resource_source.string_ptr) { - segment_size += (1 + - linked_list->data.address32.resource_source.string_length); + if (linked_list->data.address32.resource_source.string_ptr) { + segment_size += linked_list->data.address32.resource_source.string_length; + segment_size++; } break; @@ -212,9 +212,9 @@ */ segment_size = 46; - if (NULL != linked_list->data.address64.resource_source.string_ptr) { - segment_size += (1 + - linked_list->data.address64.resource_source.string_length); + if (linked_list->data.address64.resource_source.string_ptr) { + segment_size += linked_list->data.address64.resource_source.string_length; + segment_size++; } break; @@ -229,11 +229,11 @@ * Resource Source + 1 for the null. */ segment_size = 9 + - ((linked_list->data.extended_irq.number_of_interrupts - 1) * 4); + (((ACPI_SIZE) linked_list->data.extended_irq.number_of_interrupts - 1) * 4); - if (NULL != ex_irq->resource_source.string_ptr) { - segment_size += (1 + - linked_list->data.extended_irq.resource_source.string_length); + if (ex_irq && ex_irq->resource_source.string_ptr) { + segment_size += linked_list->data.extended_irq.resource_source.string_length; + segment_size++; } break; @@ -268,7 +268,7 @@ /******************************************************************************* * - * FUNCTION: Acpi_rs_calculate_list_length + * FUNCTION: Acpi_rs_get_list_length * * PARAMETERS: Byte_stream_buffer - Pointer to the resource byte stream * Byte_stream_buffer_length - Size of Byte_stream_buffer @@ -285,7 +285,7 @@ ******************************************************************************/ acpi_status -acpi_rs_calculate_list_length ( +acpi_rs_get_list_length ( u8 *byte_stream_buffer, u32 byte_stream_buffer_length, ACPI_SIZE *size_needed) @@ -304,7 +304,7 @@ u8 additional_bytes; - ACPI_FUNCTION_TRACE ("Rs_calculate_list_length"); + ACPI_FUNCTION_TRACE ("Rs_get_list_length"); while (bytes_parsed < byte_stream_buffer_length) { @@ -705,7 +705,7 @@ /******************************************************************************* * - * FUNCTION: Acpi_rs_calculate_pci_routing_table_length + * FUNCTION: Acpi_rs_get_pci_routing_table_length * * PARAMETERS: Package_object - Pointer to the package object * Buffer_size_needed - u32 pointer of the size buffer @@ -721,12 +721,12 @@ ******************************************************************************/ acpi_status -acpi_rs_calculate_pci_routing_table_length ( +acpi_rs_get_pci_routing_table_length ( acpi_operand_object *package_object, ACPI_SIZE *buffer_size_needed) { u32 number_of_elements; - u32 temp_size_needed = 0; + ACPI_SIZE temp_size_needed = 0; acpi_operand_object **top_object_list; u32 index; acpi_operand_object *package_element; @@ -735,7 +735,7 @@ u32 table_index; - ACPI_FUNCTION_TRACE ("Rs_calculate_pci_routing_table_length"); + ACPI_FUNCTION_TRACE ("Rs_get_pci_routing_table_length"); number_of_elements = package_object->package.count; @@ -788,7 +788,7 @@ /* * Was a String type found? */ - if (TRUE == name_found) { + if (name_found) { if (ACPI_TYPE_STRING == (*sub_object_list)->common.type) { /* * The length String.Length field includes the diff -Nru a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c --- a/drivers/acpi/resources/rscreate.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/resources/rscreate.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rscreate - Create resource lists/tables - * $Revision: 53 $ + * $Revision: 56 $ * ******************************************************************************/ @@ -79,11 +79,11 @@ * Pass the Byte_stream_buffer into a module that can calculate * the buffer size needed for the linked list */ - status = acpi_rs_calculate_list_length (byte_stream_start, byte_stream_buffer_length, + status = acpi_rs_get_list_length (byte_stream_start, byte_stream_buffer_length, &list_size_needed); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Status=%X List_size_needed=%X\n", - status, list_size_needed)); + status, (u32) list_size_needed)); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -104,7 +104,7 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Output_buffer %p Length %X\n", - output_buffer->pointer, output_buffer->length)); + output_buffer->pointer, (u32) output_buffer->length)); return_ACPI_STATUS (AE_OK); } @@ -157,13 +157,13 @@ /* * Get the required buffer length */ - status = acpi_rs_calculate_pci_routing_table_length (package_object, + status = acpi_rs_get_pci_routing_table_length (package_object, &buffer_size_needed); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Buffer_size_needed = %X\n", buffer_size_needed)); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Buffer_size_needed = %X\n", (u32) buffer_size_needed)); /* Validate/Allocate/Clear caller buffer */ @@ -179,7 +179,7 @@ top_object_list = package_object->package.elements; number_of_elements = package_object->package.count; buffer = output_buffer->pointer; - user_prt = (acpi_pci_routing_table *) buffer; + user_prt = ACPI_CAST_PTR (acpi_pci_routing_table, buffer); for (index = 0; index < number_of_elements; index++) { /* @@ -189,7 +189,7 @@ * be zero because we cleared the return buffer earlier */ buffer += user_prt->length; - user_prt = (acpi_pci_routing_table *) buffer; + user_prt = ACPI_CAST_PTR (acpi_pci_routing_table, buffer); /* * Fill in the Length field with the information we have at this point. @@ -257,7 +257,7 @@ (u32) ((u8 *) user_prt->source - (u8 *) output_buffer->pointer); path_buffer.pointer = user_prt->source; - status = acpi_ns_handle_to_pathname ((acpi_handle *) node, &path_buffer); + status = acpi_ns_handle_to_pathname ((acpi_handle) node, &path_buffer); user_prt->length += ACPI_STRLEN (user_prt->source) + 1; /* include null terminator */ break; @@ -316,7 +316,7 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Output_buffer %p Length %X\n", - output_buffer->pointer, output_buffer->length)); + output_buffer->pointer, (u32) output_buffer->length)); return_ACPI_STATUS (AE_OK); } @@ -359,11 +359,11 @@ * Pass the Linked_list_buffer into a module that calculates * the buffer size needed for the byte stream. */ - status = acpi_rs_calculate_byte_stream_length (linked_list_buffer, + status = acpi_rs_get_byte_stream_length (linked_list_buffer, &byte_stream_size_needed); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Byte_stream_size_needed=%X, %s\n", - byte_stream_size_needed, acpi_format_exception (status))); + (u32) byte_stream_size_needed, acpi_format_exception (status))); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -384,7 +384,7 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Output_buffer %p Length %X\n", - output_buffer->pointer, output_buffer->length)); + output_buffer->pointer, (u32) output_buffer->length)); return_ACPI_STATUS (AE_OK); } diff -Nru a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c --- a/drivers/acpi/resources/rsdump.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/resources/rsdump.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rsdump - Functions to display the resource structures. - * $Revision: 29 $ + * $Revision: 32 $ * ******************************************************************************/ @@ -31,7 +31,7 @@ ACPI_MODULE_NAME ("rsdump") -#ifdef ACPI_DEBUG +#if defined(ACPI_DEBUG) || defined(ENABLE_DEBUGGER) /******************************************************************************* * @@ -172,9 +172,9 @@ void acpi_rs_dump_start_depend_fns ( - acpi_resource_data *data) + acpi_resource_data *data) { - acpi_resource_start_dpf *sdf_data = (acpi_resource_start_dpf *) data; + acpi_resource_start_dpf *sdf_data = (acpi_resource_start_dpf *) data; ACPI_FUNCTION_ENTRY (); @@ -977,7 +977,7 @@ if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) { while (!done) { - acpi_os_printf ("Resource structure %x.\n", count++); + acpi_os_printf ("Resource structure %X.\n", count++); switch (resource->id) { case ACPI_RSTYPE_IRQ: @@ -1082,7 +1082,7 @@ if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) { - prt_element = (acpi_pci_routing_table *) buffer; + prt_element = ACPI_CAST_PTR (acpi_pci_routing_table, buffer); while (!done) { acpi_os_printf ("PCI IRQ Routing Table structure %X.\n", count++); @@ -1100,7 +1100,7 @@ buffer += prt_element->length; - prt_element = (acpi_pci_routing_table *) buffer; + prt_element = ACPI_CAST_PTR (acpi_pci_routing_table, buffer); if(0 == prt_element->length) { done = TRUE; diff -Nru a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c --- a/drivers/acpi/resources/rsio.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/resources/rsio.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rsio - IO and DMA resource descriptors - * $Revision: 17 $ + * $Revision: 20 $ * ******************************************************************************/ @@ -60,7 +60,7 @@ ACPI_SIZE *structure_size) { u8 *buffer = byte_stream_buffer; - acpi_resource *output_struct = (acpi_resource *) *output_buffer; + acpi_resource *output_struct = (void *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; ACPI_SIZE struct_size = ACPI_SIZEOF_RESOURCE (acpi_resource_io); @@ -119,7 +119,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure @@ -158,7 +158,7 @@ ACPI_SIZE *structure_size) { u8 *buffer = byte_stream_buffer; - acpi_resource *output_struct = (acpi_resource *) *output_buffer; + acpi_resource *output_struct = (void *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; ACPI_SIZE struct_size = ACPI_SIZEOF_RESOURCE (acpi_resource_fixed_io); @@ -193,7 +193,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure @@ -377,7 +377,7 @@ ACPI_SIZE *structure_size) { u8 *buffer = byte_stream_buffer; - acpi_resource *output_struct = (acpi_resource *) *output_buffer; + acpi_resource *output_struct = (void *) *output_buffer; u8 temp8 = 0; u8 index; u8 i; @@ -407,13 +407,18 @@ i++; } } + if (i == 0) { + /* Zero channels is invalid! */ + + return_ACPI_STATUS (AE_BAD_DATA); + } output_struct->data.dma.number_of_channels = i; /* * Calculate the structure size based upon the number of interrupts */ - struct_size += (output_struct->data.dma.number_of_channels - 1) * 4; + struct_size += ((ACPI_SIZE) output_struct->data.dma.number_of_channels - 1) * 4; /* * Point to Byte 2 @@ -443,7 +448,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure diff -Nru a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c --- a/drivers/acpi/resources/rsirq.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/resources/rsirq.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rsirq - IRQ resource descriptors - * $Revision: 24 $ + * $Revision: 28 $ * ******************************************************************************/ @@ -60,7 +60,7 @@ ACPI_SIZE *structure_size) { u8 *buffer = byte_stream_buffer; - acpi_resource *output_struct = (acpi_resource *) *output_buffer; + acpi_resource *output_struct = (void *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; u8 index; @@ -90,17 +90,23 @@ /* Decode the IRQ bits */ for (i = 0, index = 0; index < 16; index++) { - if((temp16 >> index) & 0x01) { + if ((temp16 >> index) & 0x01) { output_struct->data.irq.interrupts[i] = index; i++; } } + + if (i == 0) { + /* Zero interrupts is invalid! */ + + return_ACPI_STATUS (AE_BAD_DATA); + } output_struct->data.irq.number_of_interrupts = i; /* * Calculate the structure size based upon the number of interrupts */ - struct_size += (output_struct->data.irq.number_of_interrupts - 1) * 4; + struct_size += ((ACPI_SIZE) output_struct->data.irq.number_of_interrupts - 1) * 4; /* * Point to Byte 3 if it is used @@ -149,7 +155,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure @@ -279,10 +285,10 @@ ACPI_SIZE *structure_size) { u8 *buffer = byte_stream_buffer; - acpi_resource *output_struct = (acpi_resource *) *output_buffer; + acpi_resource *output_struct = (void *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; - NATIVE_CHAR *temp_ptr; + u8 *temp_ptr; u8 index; ACPI_SIZE struct_size = ACPI_SIZEOF_RESOURCE (acpi_resource_ext_irq); @@ -351,8 +357,8 @@ * Cycle through every IRQ in the table */ for (index = 0; index < temp8; index++) { - output_struct->data.extended_irq.interrupts[index] = - (u32)*buffer; + ACPI_MOVE_UNALIGNED32_TO_32 ( + &output_struct->data.extended_irq.interrupts[index], buffer); /* Point to the next IRQ */ @@ -367,7 +373,7 @@ * stream that are default. */ if (*bytes_consumed > - (u32)(output_struct->data.extended_irq.number_of_interrupts * 4) + 5) { + ((ACPI_SIZE) output_struct->data.extended_irq.number_of_interrupts * 4) + 5) { /* Dereference the Index */ temp8 = *buffer; @@ -383,7 +389,7 @@ output_struct->data.extended_irq.resource_source.string_ptr = (NATIVE_CHAR *)(output_struct + struct_size); - temp_ptr = output_struct->data.extended_irq.resource_source.string_ptr; + temp_ptr = (u8 *) output_struct->data.extended_irq.resource_source.string_ptr; /* Copy the string into the buffer */ @@ -419,7 +425,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure @@ -470,7 +476,7 @@ /* * Set a pointer to the Length field - to be filled in later */ - length_field = (u16 *)buffer; + length_field = ACPI_CAST_PTR (u16, buffer); buffer += 2; /* diff -Nru a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c --- a/drivers/acpi/resources/rslist.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/resources/rslist.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rslist - Linked list utilities - * $Revision: 26 $ + * $Revision: 30 $ * ******************************************************************************/ @@ -70,6 +70,11 @@ * Large Resource Type -- All bits are valid */ return (resource_start_byte); + + + default: + /* No other types of resource descriptor */ + break; } return (0xFF); @@ -99,7 +104,7 @@ u8 *output_buffer) { acpi_status status; - u32 bytes_parsed = 0; + ACPI_SIZE bytes_parsed = 0; u8 resource_type = 0; ACPI_SIZE bytes_consumed = 0; u8 *buffer = output_buffer; @@ -111,7 +116,7 @@ while (bytes_parsed < byte_stream_buffer_length && - FALSE == end_tag_processed) { + !end_tag_processed) { /* * The next byte in the stream is the resource type */ @@ -265,9 +270,9 @@ default: /* - * Invalid/Unknowns resource type + * Invalid/Unknown resource type */ - status = AE_AML_ERROR; + status = AE_AML_INVALID_RESOURCE_TYPE; break; } @@ -288,7 +293,7 @@ /* * Set the Buffer to the next structure */ - resource = (acpi_resource *)buffer; + resource = ACPI_CAST_PTR (acpi_resource, buffer); resource->length = ACPI_ALIGN_RESOURCE_SIZE(resource->length); buffer += ACPI_ALIGN_RESOURCE_SIZE(structure_size); @@ -297,8 +302,8 @@ /* * Check the reason for exiting the while loop */ - if (TRUE != end_tag_processed) { - return_ACPI_STATUS (AE_AML_ERROR); + if (!end_tag_processed) { + return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); } return_ACPI_STATUS (AE_OK); @@ -312,7 +317,7 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Byte_steam_size_needed - Calculated size of the byte stream * needed from calling - * Acpi_rs_calculate_byte_stream_length() + * Acpi_rs_get_byte_stream_length() * The size of the Output_buffer is * guaranteed to be >= * Byte_stream_size_needed @@ -329,7 +334,7 @@ acpi_status acpi_rs_list_to_byte_stream ( acpi_resource *linked_list, - u32 byte_stream_size_needed, + ACPI_SIZE byte_stream_size_needed, u8 *output_buffer) { acpi_status status; diff -Nru a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/resources/rsmemory.c --- a/drivers/acpi/resources/rsmemory.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/resources/rsmemory.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rsmem24 - Memory resource descriptors - * $Revision: 17 $ + * $Revision: 20 $ * ******************************************************************************/ @@ -60,7 +60,7 @@ ACPI_SIZE *structure_size) { u8 *buffer = byte_stream_buffer; - acpi_resource *output_struct = (acpi_resource *) *output_buffer; + acpi_resource *output_struct = (void *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; ACPI_SIZE struct_size = ACPI_SIZEOF_RESOURCE (acpi_resource_mem24); @@ -76,7 +76,7 @@ ACPI_MOVE_UNALIGNED16_TO_16 (&temp16, buffer); buffer += 2; - *bytes_consumed = temp16 + 3; + *bytes_consumed = (ACPI_SIZE) temp16 + 3; output_struct->id = ACPI_RSTYPE_MEM24; /* @@ -116,7 +116,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure @@ -237,7 +237,7 @@ ACPI_SIZE *structure_size) { u8 *buffer = byte_stream_buffer; - acpi_resource *output_struct = (acpi_resource *) *output_buffer; + acpi_resource *output_struct = (void *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; ACPI_SIZE struct_size = ACPI_SIZEOF_RESOURCE (acpi_resource_mem32); @@ -253,7 +253,7 @@ ACPI_MOVE_UNALIGNED16_TO_16 (&temp16, buffer); buffer += 2; - *bytes_consumed = temp16 + 3; + *bytes_consumed = (ACPI_SIZE) temp16 + 3; output_struct->id = ACPI_RSTYPE_MEM32; @@ -303,7 +303,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure @@ -342,7 +342,7 @@ ACPI_SIZE *structure_size) { u8 *buffer = byte_stream_buffer; - acpi_resource *output_struct = (acpi_resource *) *output_buffer; + acpi_resource *output_struct = (void *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; ACPI_SIZE struct_size = ACPI_SIZEOF_RESOURCE (acpi_resource_fixed_mem32); @@ -358,7 +358,7 @@ ACPI_MOVE_UNALIGNED16_TO_16 (&temp16, buffer); buffer += 2; - *bytes_consumed = temp16 + 3; + *bytes_consumed = (ACPI_SIZE) temp16 + 3; output_struct->id = ACPI_RSTYPE_FIXED_MEM32; @@ -385,7 +385,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure diff -Nru a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c --- a/drivers/acpi/resources/rsmisc.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/resources/rsmisc.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rsmisc - Miscellaneous resource descriptors - * $Revision: 20 $ + * $Revision: 24 $ * ******************************************************************************/ @@ -59,7 +59,7 @@ u8 **output_buffer, ACPI_SIZE *structure_size) { - acpi_resource *output_struct = (acpi_resource *) *output_buffer; + acpi_resource *output_struct = (void *) *output_buffer; ACPI_SIZE struct_size = ACPI_RESOURCE_LENGTH; @@ -170,7 +170,7 @@ ACPI_SIZE *structure_size) { u8 *buffer = byte_stream_buffer; - acpi_resource *output_struct = (acpi_resource *) *output_buffer; + acpi_resource *output_struct = (void *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; u8 index; @@ -197,7 +197,7 @@ /* Calculate bytes consumed */ - *bytes_consumed = temp16 + 3; + *bytes_consumed = (ACPI_SIZE) temp16 + 3; /* Point to the first vendor byte */ @@ -211,7 +211,7 @@ /* Calculate bytes consumed */ - *bytes_consumed = temp16 + 1; + *bytes_consumed = (ACPI_SIZE) temp16 + 1; /* Point to the first vendor byte */ @@ -236,7 +236,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure @@ -297,7 +297,7 @@ * Small Item, Set the descriptor field */ temp8 = 0x70; - temp8 |= linked_list->data.vendor_specific.length; + temp8 |= (u8) linked_list->data.vendor_specific.length; *buffer = temp8; buffer += 1; @@ -350,7 +350,7 @@ ACPI_SIZE *structure_size) { u8 *buffer = byte_stream_buffer; - acpi_resource *output_struct = (acpi_resource *) *output_buffer; + acpi_resource *output_struct = (void *) *output_buffer; u8 temp8 = 0; ACPI_SIZE struct_size = ACPI_SIZEOF_RESOURCE (acpi_resource_start_dpf); @@ -380,7 +380,7 @@ output_struct->data.start_dpf.compatibility_priority = temp8 & 0x03; if (3 == output_struct->data.start_dpf.compatibility_priority) { - return_ACPI_STATUS (AE_AML_ERROR); + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE); } /* @@ -389,7 +389,7 @@ output_struct->data.start_dpf.performance_robustness = (temp8 >> 2) & 0x03; if (3 == output_struct->data.start_dpf.performance_robustness) { - return_ACPI_STATUS (AE_AML_ERROR); + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE); } } else { @@ -403,7 +403,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure @@ -441,7 +441,7 @@ u8 **output_buffer, ACPI_SIZE *structure_size) { - acpi_resource *output_struct = (acpi_resource *) *output_buffer; + acpi_resource *output_struct = (void *) *output_buffer; ACPI_SIZE struct_size = ACPI_RESOURCE_LENGTH; @@ -461,7 +461,7 @@ /* * Set the Length parameter */ - output_struct->length = struct_size; + output_struct->length = (u32) struct_size; /* * Return the final size of the structure diff -Nru a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c --- a/drivers/acpi/resources/rsutils.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/resources/rsutils.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rsutils - Utilities for the resource manager - * $Revision: 29 $ + * $Revision: 30 $ * ******************************************************************************/ @@ -317,7 +317,7 @@ /* * Set up the parameter object */ - params[0]->buffer.length = buffer.length; + params[0]->buffer.length = (u32) buffer.length; params[0]->buffer.pointer = buffer.pointer; params[1] = NULL; diff -Nru a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c --- a/drivers/acpi/resources/rsxface.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/resources/rsxface.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rsxface - Public interfaces to the resource manager - * $Revision: 18 $ + * $Revision: 19 $ * ******************************************************************************/ @@ -25,8 +25,6 @@ #include "acpi.h" -#include "acinterp.h" -#include "acnamesp.h" #include "acresrc.h" #define _COMPONENT ACPI_RESOURCES diff -Nru a/drivers/acpi/system.c b/drivers/acpi/system.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/system.c Sun Jun 2 18:44:58 2002 @@ -0,0 +1,1310 @@ +/* + * acpi_system.c - ACPI System Driver ($Revision: 57 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#define ACPI_C + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + +#ifdef CONFIG_X86 +#ifdef CONFIG_ACPI_SLEEP +#include +#endif +#endif + + +#define _COMPONENT ACPI_SYSTEM_COMPONENT +ACPI_MODULE_NAME ("acpi_system") + +#define PREFIX "ACPI: " + +extern FADT_DESCRIPTOR acpi_fadt; + +static int acpi_system_add (struct acpi_device *device); +static int acpi_system_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_system_driver = { + name: ACPI_SYSTEM_DRIVER_NAME, + class: ACPI_SYSTEM_CLASS, + ids: ACPI_SYSTEM_HID, + ops: { + add: acpi_system_add, + remove: acpi_system_remove + }, +}; + +struct acpi_system +{ + acpi_handle handle; + u8 states[ACPI_S_STATE_COUNT]; +}; + +/* Global vars for handling event proc entry */ +static spinlock_t acpi_system_event_lock = SPIN_LOCK_UNLOCKED; +int event_is_open = 0; +extern struct list_head acpi_bus_event_list; +extern wait_queue_head_t acpi_bus_event_queue; + +/* -------------------------------------------------------------------------- + System Sleep + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_PM + +static void +acpi_power_off (void) +{ + acpi_enter_sleep_state_prep(ACPI_STATE_S5); + ACPI_DISABLE_IRQS(); + acpi_enter_sleep_state(ACPI_STATE_S5); +} + +#endif /*CONFIG_PM*/ + + +#ifdef CONFIG_ACPI_SLEEP + +/** + * acpi_system_restore_state - OS-specific restoration of state + * @state: sleep state we're exiting + * + * Note that if we're coming back from S4, the memory image should have already + * been loaded from the disk and is already in place. (Otherwise how else would we + * be here?). + */ +acpi_status +acpi_system_restore_state ( + u32 state) +{ + /* restore processor state + * We should only be here if we're coming back from STR or STD. + * And, in the case of the latter, the memory image should have already + * been loaded from disk. + */ + if (state > ACPI_STATE_S1) + acpi_restore_state_mem(); + + /* wait for power to come back */ + mdelay(10); +#ifdef HAVE_NEW_DEVICE_MODEL + /* turn all the devices back on */ + device_resume(RESUME_POWER_ON); + + /* enable interrupts once again */ + ACPI_ENABLE_IRQS(); + + /* restore device context */ + device_resume(RESUME_RESTORE_STATE); +#endif + + if (dmi_broken & BROKEN_INIT_AFTER_S1) { + printk("Broken toshiba laptop -> kicking interrupts\n"); + init_8259A(0); + } + + return AE_OK; +} + +/** + * acpi_system_save_state - save OS specific state and power down devices + * @state: sleep state we're entering. + * + * This handles saving all context to memory, and possibly disk. + * First, we call to the device driver layer to save device state. + * Once we have that, we save whatevery processor and kernel state we + * need to memory. + * If we're entering S4, we then write the memory image to disk. + * + * Only then is it safe for us to power down devices, since we may need + * the disks and upstream buses to write to. + */ +acpi_status +acpi_system_save_state( + u32 state) +{ + int error = 0; + +#ifdef HAVE_NEW_DEVICE_MODEL + /* Send notification to devices that they will be suspended. + * If any device or driver cannot make the transition, either up + * or down, we'll get an error back. + */ + error = device_suspend(state, SUSPEND_NOTIFY); + if (error) + return AE_ERROR; +#endif + if (state < ACPI_STATE_S5) { + +#ifdef HAVE_NEW_DEVICE_MODEL + /* Tell devices to stop I/O and actually save their state. + * It is theoretically possible that something could fail, + * so handle that gracefully.. + */ + error = device_suspend(state, SUSPEND_SAVE_STATE); + if (error) { + /* tell devices to restore state if they have + * it saved and to start taking I/O requests. + */ + device_resume(RESUME_RESTORE_STATE); + return error; + } +#endif + + /* flush caches */ + ACPI_FLUSH_CPU_CACHE(); + + /* Do arch specific saving of state. */ + if (state > ACPI_STATE_S1) { + error = acpi_save_state_mem(); + + if (!error && (state == ACPI_STATE_S4)) + error = acpi_save_state_disk(); + +#ifdef HAVE_NEW_DEVICE_MODEL + if (error) { + device_resume(RESUME_RESTORE_STATE); + return error; + } +#endif + } + } +#ifdef HAVE_NEW_DEVICE_MODEL + /* disable interrupts + * Note that acpi_suspend -- our caller -- will do this once we return. + * But, we want it done early, so we don't get any suprises during + * the device suspend sequence. + */ + ACPI_DISABLE_IRQS(); + + /* Unconditionally turn off devices. + * Obvious if we enter a sleep state. + * If entering S5 (soft off), this should put devices in a + * quiescent state. + */ + error = device_suspend(state, SUSPEND_POWER_DOWN); + + /* We're pretty screwed if we got an error from this. + * We try to recover by simply calling our own restore_state + * function; see above for definition. + * + * If it's S5 though, go through with it anyway.. + */ + if (error && state != ACPI_STATE_S5) + acpi_system_restore_state(state); +#endif + return error ? AE_ERROR : AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: acpi_system_suspend + * + * PARAMETERS: %state: Sleep state to enter. + * + * RETURN: acpi_status, whether or not we successfully entered and + * exited sleep. + * + * DESCRIPTION: Perform OS-specific action to enter sleep state. + * This is the final step in going to sleep, per spec. If we + * know we're coming back (i.e. not entering S5), we save the + * processor flags. [ We'll have to save and restore them anyway, + * so we use the arch-agnostic save_flags and restore_flags + * here.] We then set the place to return to in arch-specific + * globals using arch_set_return_point. Finally, we call the + * ACPI function to write the proper values to I/O ports. + * + ****************************************************************************/ + +acpi_status +acpi_system_suspend( + u32 state) +{ + acpi_status status = AE_ERROR; +#if 0 + unsigned long flags = 0; + + /* this is very broken, so don't do anything until it's fixed */ + save_flags(flags); + + switch (state) + { + case ACPI_STATE_S1: + /* do nothing */ + break; + + case ACPI_STATE_S2: + case ACPI_STATE_S3: + save_processor_context(); + /* TODO: this is horribly broken, fix it */ + /* TODO: inline this function in acpi_suspend,or something. */ + break; + } + + barrier(); + status = acpi_enter_sleep_state(state); + +acpi_sleep_done: + + restore_processor_context(); + fix_processor_context(); + + restore_flags(flags); +#endif + printk("ACPI: ACPI-based suspend currently broken, aborting\n"); + + return status; +} + + +/** + * acpi_suspend - OS-agnostic system suspend/resume support (S? states) + * @state: state we're entering + * + */ +acpi_status +acpi_suspend ( + u32 state) +{ + acpi_status status; + + /* get out if state is invalid */ + if (state < ACPI_STATE_S1 || state > ACPI_STATE_S5) + return AE_ERROR; + + /* do we have a wakeup address for S2 and S3? */ + if (state == ACPI_STATE_S2 || state == ACPI_STATE_S3) { + if (!acpi_wakeup_address) + return AE_ERROR; + acpi_set_firmware_waking_vector((ACPI_PHYSICAL_ADDRESS) acpi_wakeup_address); + } + + acpi_enter_sleep_state_prep(state); + + status = acpi_system_save_state(state); + if (!ACPI_SUCCESS(status)) + return status; + + /* disable interrupts and flush caches */ + ACPI_DISABLE_IRQS(); + ACPI_FLUSH_CPU_CACHE(); + + /* perform OS-specific sleep actions */ + status = acpi_system_suspend(state); + + /* Even if we failed to go to sleep, all of the devices are in an suspended + * mode. So, we run these unconditionaly to make sure we have a usable system + * no matter what. + */ + acpi_system_restore_state(state); + acpi_leave_sleep_state(state); + + /* make sure interrupts are enabled */ + ACPI_ENABLE_IRQS(); + + /* reset firmware waking vector */ + acpi_set_firmware_waking_vector((ACPI_PHYSICAL_ADDRESS) 0); + + return status; +} + +#endif /* CONFIG_ACPI_SLEEP */ + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +static int +acpi_system_read_info ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_system *system = (struct acpi_system *) data; + char *p = page; + int size = 0; + u32 i = 0; + + ACPI_FUNCTION_TRACE("acpi_system_read_info"); + + if (!system || (off != 0)) + goto end; + + p += sprintf(p, "version: %x\n", ACPI_CA_VERSION); + + p += sprintf(p, "states: "); + for (i=0; istates[i]) + p += sprintf(p, "S%d ", i); + } + p += sprintf(p, "\n"); + +end: + size = (p - page); + if (size <= off+count) *eof = 1; + *start = page + off; + size -= off; + if (size>count) size = count; + if (size<0) size = 0; + + return_VALUE(size); +} + +static int acpi_system_open_event(struct inode *inode, struct file *file); +static ssize_t acpi_system_read_event (struct file*, char*, size_t, loff_t*); +static int acpi_system_close_event(struct inode *inode, struct file *file); +static unsigned int acpi_system_poll_event(struct file *file, poll_table *wait); + + +static struct file_operations acpi_system_event_ops = { + open: acpi_system_open_event, + read: acpi_system_read_event, + release: acpi_system_close_event, + poll: acpi_system_poll_event, +}; + +static int +acpi_system_open_event(struct inode *inode, struct file *file) +{ + spin_lock_irq (&acpi_system_event_lock); + + if(event_is_open) + goto out_busy; + + event_is_open = 1; + + spin_unlock_irq (&acpi_system_event_lock); + return 0; + +out_busy: + spin_unlock_irq (&acpi_system_event_lock); + return -EBUSY; +} + +static ssize_t +acpi_system_read_event ( + struct file *file, + char *buffer, + size_t count, + loff_t *ppos) +{ + int result = 0; + struct acpi_bus_event event; + static char str[ACPI_MAX_STRING]; + static int chars_remaining = 0; + static char *ptr; + + + ACPI_FUNCTION_TRACE("acpi_system_read_event"); + + if (!chars_remaining) { + memset(&event, 0, sizeof(struct acpi_bus_event)); + + if ((file->f_flags & O_NONBLOCK) + && (list_empty(&acpi_bus_event_list))) + return_VALUE(-EAGAIN); + + result = acpi_bus_receive_event(&event); + if (result) { + return_VALUE(-EIO); + } + + chars_remaining = sprintf(str, "%s %s %08x %08x\n", + event.device_class?event.device_class:"", + event.bus_id?event.bus_id:"", + event.type, event.data); + ptr = str; + } + + if (chars_remaining < count) { + count = chars_remaining; + } + + if (copy_to_user(buffer, ptr, count)) + return_VALUE(-EFAULT); + + *ppos += count; + chars_remaining -= count; + ptr += count; + + return_VALUE(count); +} + +static int +acpi_system_close_event(struct inode *inode, struct file *file) +{ + spin_lock_irq (&acpi_system_event_lock); + event_is_open = 0; + spin_unlock_irq (&acpi_system_event_lock); + return 0; +} + +static unsigned int +acpi_system_poll_event( + struct file *file, + poll_table *wait) +{ + poll_wait(file, &acpi_bus_event_queue, wait); + if (!list_empty(&acpi_bus_event_list)) + return POLLIN | POLLRDNORM; + return 0; +} + +static ssize_t acpi_system_read_dsdt (struct file*, char*, size_t, loff_t*); + +static struct file_operations acpi_system_dsdt_ops = { + read: acpi_system_read_dsdt, +}; + +static ssize_t +acpi_system_read_dsdt ( + struct file *file, + char *buffer, + size_t count, + loff_t *ppos) +{ + acpi_status status = AE_OK; + acpi_buffer dsdt = {ACPI_ALLOCATE_BUFFER, NULL}; + void *data = 0; + size_t size = 0; + + ACPI_FUNCTION_TRACE("acpi_system_read_dsdt"); + + status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + if (*ppos < dsdt.length) { + data = dsdt.pointer + file->f_pos; + size = dsdt.length - file->f_pos; + if (size > count) + size = count; + if (copy_to_user(buffer, data, size)) { + kfree(dsdt.pointer); + return_VALUE(-EFAULT); + } + } + + kfree(dsdt.pointer); + + *ppos += size; + + return_VALUE(size); +} + + +static ssize_t acpi_system_read_fadt (struct file*, char*, size_t, loff_t*); + +static struct file_operations acpi_system_fadt_ops = { + read: acpi_system_read_fadt, +}; + +static ssize_t +acpi_system_read_fadt ( + struct file *file, + char *buffer, + size_t count, + loff_t *ppos) +{ + acpi_status status = AE_OK; + acpi_buffer fadt = {ACPI_ALLOCATE_BUFFER, NULL}; + void *data = 0; + size_t size = 0; + + ACPI_FUNCTION_TRACE("acpi_system_read_fadt"); + + status = acpi_get_table(ACPI_TABLE_FADT, 1, &fadt); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + if (*ppos < fadt.length) { + data = fadt.pointer + file->f_pos; + size = fadt.length - file->f_pos; + if (size > count) + size = count; + if (copy_to_user(buffer, data, size)) { + kfree(fadt.pointer); + return_VALUE(-EFAULT); + } + } + + kfree(fadt.pointer); + + *ppos += size; + + return_VALUE(size); +} + + +#ifdef ACPI_DEBUG + +static int +acpi_system_read_debug ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + char *p = page; + int size = 0; + + if (off != 0) + goto end; + + switch ((unsigned long) data) { + case 0: + p += sprintf(p, "0x%08x\n", acpi_dbg_layer); + break; + case 1: + p += sprintf(p, "0x%08x\n", acpi_dbg_level); + break; + default: + p += sprintf(p, "Invalid debug option\n"); + break; + } + +end: + size = (p - page); + if (size <= off+count) *eof = 1; + *start = page + off; + size -= off; + if (size>count) size = count; + if (size<0) size = 0; + + return size; +} + + +static int +acpi_system_write_debug ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + char debug_string[12] = {'\0'}; + + ACPI_FUNCTION_TRACE("acpi_system_write_debug"); + + if (count > sizeof(debug_string) - 1) + return_VALUE(-EINVAL); + + if (copy_from_user(debug_string, buffer, count)) + return_VALUE(-EFAULT); + + debug_string[count] = '\0'; + + switch ((unsigned long) data) { + case 0: + acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0); + break; + case 1: + acpi_dbg_level = simple_strtoul(debug_string, NULL, 0); + break; + default: + return_VALUE(-EINVAL); + } + + return_VALUE(count); +} + +#endif /* ACPI_DEBUG */ + + +#ifdef CONFIG_ACPI_SLEEP + +static int +acpi_system_read_sleep ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_system *system = (struct acpi_system *) data; + char *p = page; + int size; + int i; + + ACPI_FUNCTION_TRACE("acpi_system_read_sleep"); + + if (!system || (off != 0)) + goto end; + + for (i = 0; i <= ACPI_STATE_S5; i++) { + if (system->states[i]) + p += sprintf(p,"S%d ", i); + } + + p += sprintf(p, "\n"); + +end: + size = (p - page); + if (size <= off+count) *eof = 1; + *start = page + off; + size -= off; + if (size>count) size = count; + if (size<0) size = 0; + + return_VALUE(size); +} + + +static int +acpi_system_write_sleep ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + acpi_status status = AE_OK; + struct acpi_system *system = (struct acpi_system *) data; + char state_string[12] = {'\0'}; + u32 state = 0; + + ACPI_FUNCTION_TRACE("acpi_system_write_sleep"); + + if (!system || (count > sizeof(state_string) - 1)) + return_VALUE(-EINVAL); + + if (copy_from_user(state_string, buffer, count)) + return_VALUE(-EFAULT); + + state_string[count] = '\0'; + + state = simple_strtoul(state_string, NULL, 0); + + if (!system->states[state]) + return_VALUE(-ENODEV); + + +#ifdef CONFIG_SOFTWARE_SUSPEND + if (state == 4) { + software_suspend(); + return_VALUE(count); + } +#endif + status = acpi_suspend(state); + + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + return_VALUE(count); +} + + +static int +acpi_system_read_alarm ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *context) +{ + char *p = page; + int size = 0; + u32 sec, min, hr; + u32 day, mo, yr; + + ACPI_FUNCTION_TRACE("acpi_system_read_alarm"); + + if (off != 0) + goto end; + + spin_lock(&rtc_lock); + + sec = CMOS_READ(RTC_SECONDS_ALARM); + min = CMOS_READ(RTC_MINUTES_ALARM); + hr = CMOS_READ(RTC_HOURS_ALARM); + +#if 0 /* If we ever get an FACP with proper values... */ + if (acpi_gbl_FADT->day_alrm) + day = CMOS_READ(acpi_gbl_FADT->day_alrm); + else + day = CMOS_READ(RTC_DAY_OF_MONTH); + if (acpi_gbl_FADT->mon_alrm) + mo = CMOS_READ(acpi_gbl_FADT->mon_alrm); + else + mo = CMOS_READ(RTC_MONTH);; + if (acpi_gbl_FADT->century) + yr = CMOS_READ(acpi_gbl_FADT->century) * 100 + CMOS_READ(RTC_YEAR); + else + yr = CMOS_READ(RTC_YEAR); +#else + day = CMOS_READ(RTC_DAY_OF_MONTH); + mo = CMOS_READ(RTC_MONTH); + yr = CMOS_READ(RTC_YEAR); +#endif + + spin_unlock(&rtc_lock); + + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hr); + BCD_TO_BIN(day); + BCD_TO_BIN(mo); + BCD_TO_BIN(yr); + +#if 0 + /* we're trusting the FADT (see above)*/ +#else + /* If we're not trusting the FADT, we should at least make it + * right for _this_ century... ehm, what is _this_ century? + * + * TBD: + * ASAP: find piece of code in the kernel, e.g. star tracker driver, + * which we can trust to determine the century correctly. Atom + * watch driver would be nice, too... + * + * if that has not happened, change for first release in 2050: + * if (yr<50) + * yr += 2100; + * else + * yr += 2000; // current line of code + * + * if that has not happened either, please do on 2099/12/31:23:59:59 + * s/2000/2100 + * + */ + yr += 2000; +#endif + + p += sprintf(p,"%4.4u-", yr); + p += (mo > 12) ? sprintf(p, "**-") : sprintf(p, "%2.2u-", mo); + p += (day > 31) ? sprintf(p, "** ") : sprintf(p, "%2.2u ", day); + p += (hr > 23) ? sprintf(p, "**:") : sprintf(p, "%2.2u:", hr); + p += (min > 59) ? sprintf(p, "**:") : sprintf(p, "%2.2u:", min); + p += (sec > 59) ? sprintf(p, "**\n") : sprintf(p, "%2.2u\n", sec); + + end: + size = p - page; + if (size < count) *eof = 1; + else if (size > count) size = count; + if (size < 0) size = 0; + *start = page; + + return_VALUE(size); +} + + +static int +get_date_field ( + char **p, + u32 *value) +{ + char *next = NULL; + char *string_end = NULL; + int result = -EINVAL; + + /* + * Try to find delimeter, only to insert null. The end of the + * string won't have one, but is still valid. + */ + next = strpbrk(*p, "- :"); + if (next) + *next++ = '\0'; + + *value = simple_strtoul(*p, &string_end, 10); + + /* Signal success if we got a good digit */ + if (string_end != *p) + result = 0; + + if (next) + *p = next; + + return result; +} + + +static int +acpi_system_write_alarm ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + char alarm_string[30] = {'\0'}; + char *p = alarm_string; + u32 sec, min, hr, day, mo, yr; + int adjust = 0; + unsigned char rtc_control = 0; + + ACPI_FUNCTION_TRACE("acpi_system_write_alarm"); + + if (count > sizeof(alarm_string) - 1) + return_VALUE(-EINVAL); + + if (copy_from_user(alarm_string, buffer, count)) + return_VALUE(-EFAULT); + + alarm_string[count] = '\0'; + + /* check for time adjustment */ + if (alarm_string[0] == '+') { + p++; + adjust = 1; + } + + if ((result = get_date_field(&p, &yr))) + goto end; + if ((result = get_date_field(&p, &mo))) + goto end; + if ((result = get_date_field(&p, &day))) + goto end; + if ((result = get_date_field(&p, &hr))) + goto end; + if ((result = get_date_field(&p, &min))) + goto end; + if ((result = get_date_field(&p, &sec))) + goto end; + + if (sec > 59) { + min += 1; + sec -= 60; + } + if (min > 59) { + hr += 1; + min -= 60; + } + if (hr > 23) { + day += 1; + hr -= 24; + } + if (day > 31) { + mo += 1; + day -= 31; + } + if (mo > 12) { + yr += 1; + mo -= 12; + } + + spin_lock_irq(&rtc_lock); + + rtc_control = CMOS_READ(RTC_CONTROL); + if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BIN_TO_BCD(yr); + BIN_TO_BCD(mo); + BIN_TO_BCD(day); + BIN_TO_BCD(hr); + BIN_TO_BCD(min); + BIN_TO_BCD(sec); + } + + if (adjust) { + yr += CMOS_READ(RTC_YEAR); + mo += CMOS_READ(RTC_MONTH); + day += CMOS_READ(RTC_DAY_OF_MONTH); + hr += CMOS_READ(RTC_HOURS); + min += CMOS_READ(RTC_MINUTES); + sec += CMOS_READ(RTC_SECONDS); + } + + spin_unlock_irq(&rtc_lock); + + if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BCD_TO_BIN(yr); + BCD_TO_BIN(mo); + BCD_TO_BIN(day); + BCD_TO_BIN(hr); + BCD_TO_BIN(min); + BCD_TO_BIN(sec); + } + + if (sec > 59) { + min++; + sec -= 60; + } + if (min > 59) { + hr++; + min -= 60; + } + if (hr > 23) { + day++; + hr -= 24; + } + if (day > 31) { + mo++; + day -= 31; + } + if (mo > 12) { + yr++; + mo -= 12; + } + if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BIN_TO_BCD(yr); + BIN_TO_BCD(mo); + BIN_TO_BCD(day); + BIN_TO_BCD(hr); + BIN_TO_BCD(min); + BIN_TO_BCD(sec); + } + + spin_lock_irq(&rtc_lock); + + /* write the fields the rtc knows about */ + CMOS_WRITE(hr, RTC_HOURS_ALARM); + CMOS_WRITE(min, RTC_MINUTES_ALARM); + CMOS_WRITE(sec, RTC_SECONDS_ALARM); + + /* + * If the system supports an enhanced alarm it will have non-zero + * offsets into the CMOS RAM here -- which for some reason are pointing + * to the RTC area of memory. + */ +#if 0 + if (acpi_gbl_FADT->day_alrm) + CMOS_WRITE(day, acpi_gbl_FADT->day_alrm); + if (acpi_gbl_FADT->mon_alrm) + CMOS_WRITE(mo, acpi_gbl_FADT->mon_alrm); + if (acpi_gbl_FADT->century) + CMOS_WRITE(yr/100, acpi_gbl_FADT->century); +#endif + /* enable the rtc alarm interrupt */ + if (!(rtc_control & RTC_AIE)) { + rtc_control |= RTC_AIE; + CMOS_WRITE(rtc_control,RTC_CONTROL); + CMOS_READ(RTC_INTR_FLAGS); + } + + spin_unlock_irq(&rtc_lock); + + acpi_set_register(ACPI_BITREG_RT_CLOCK_ENABLE, 1, ACPI_MTX_LOCK); + + file->f_pos += count; + + result = 0; +end: + return_VALUE(result ? result : count); +} + +#endif /*CONFIG_ACPI_SLEEP*/ + + +static int +acpi_system_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_system_add_fs"); + + if (!device) + return_VALUE(-EINVAL); + + /* 'info' [R] */ + entry = create_proc_entry(ACPI_SYSTEM_FILE_INFO, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_SYSTEM_FILE_INFO)); + else { + entry->read_proc = acpi_system_read_info; + entry->data = acpi_driver_data(device); + } + + /* 'dsdt' [R] */ + entry = create_proc_entry(ACPI_SYSTEM_FILE_DSDT, + S_IRUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_SYSTEM_FILE_DSDT)); + else + entry->proc_fops = &acpi_system_dsdt_ops; + + /* 'fadt' [R] */ + entry = create_proc_entry(ACPI_SYSTEM_FILE_FADT, + S_IRUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_SYSTEM_FILE_FADT)); + else + entry->proc_fops = &acpi_system_fadt_ops; + + /* 'event' [R] */ + entry = create_proc_entry(ACPI_SYSTEM_FILE_EVENT, + S_IRUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_SYSTEM_FILE_EVENT)); + else + entry->proc_fops = &acpi_system_event_ops; + +#ifdef CONFIG_ACPI_SLEEP + + /* 'sleep' [R/W]*/ + entry = create_proc_entry(ACPI_SYSTEM_FILE_SLEEP, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_SYSTEM_FILE_SLEEP)); + else { + entry->read_proc = acpi_system_read_sleep; + entry->write_proc = acpi_system_write_sleep; + entry->data = acpi_driver_data(device); + } + + /* 'alarm' [R/W] */ + entry = create_proc_entry(ACPI_SYSTEM_FILE_ALARM, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_SYSTEM_FILE_ALARM)); + else { + entry->read_proc = acpi_system_read_alarm; + entry->write_proc = acpi_system_write_alarm; + entry->data = acpi_driver_data(device); + } + +#endif /*CONFIG_ACPI_SLEEP*/ + +#ifdef ACPI_DEBUG + + /* 'debug_layer' [R/W] */ + entry = create_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_SYSTEM_FILE_DEBUG_LAYER)); + else { + entry->read_proc = acpi_system_read_debug; + entry->write_proc = acpi_system_write_debug; + entry->data = (void *) 0; + } + + /* 'debug_level' [R/W] */ + entry = create_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LEVEL, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_SYSTEM_FILE_DEBUG_LEVEL)); + else { + entry->read_proc = acpi_system_read_debug; + entry->write_proc = acpi_system_write_debug; + entry->data = (void *) 1; + } + +#endif /*ACPI_DEBUG*/ + + return_VALUE(0); +} + + +static int +acpi_system_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_system_remove_fs"); + + if (!device) + return_VALUE(-EINVAL); + + remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_device_dir(device)); + remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_device_dir(device)); + remove_proc_entry(ACPI_SYSTEM_FILE_EVENT, acpi_device_dir(device)); +#ifdef CONFIG_ACPI_SLEEP + remove_proc_entry(ACPI_SYSTEM_FILE_SLEEP, acpi_device_dir(device)); + remove_proc_entry(ACPI_SYSTEM_FILE_ALARM, acpi_device_dir(device)); +#endif +#ifdef ACPI_DEBUG + remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, + acpi_device_dir(device)); + remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LEVEL, + acpi_device_dir(device)); +#endif + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +#if defined(CONFIG_MAGIC_SYSRQ) && defined(CONFIG_PM) + +/* Simple wrapper calling power down function. */ +static void acpi_sysrq_power_off(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) +{ + acpi_power_off(); +} + +struct sysrq_key_op sysrq_acpi_poweroff_op = { + handler: &acpi_sysrq_power_off, + help_msg: "Off", + action_msg: "Power Off\n" +}; + +#endif /* CONFIG_MAGIC_SYSRQ */ + +static int +acpi_system_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_system *system = NULL; + u8 i = 0; + + ACPI_FUNCTION_TRACE("acpi_system_add"); + + if (!device) + return_VALUE(-EINVAL); + + system = kmalloc(sizeof(struct acpi_system), GFP_KERNEL); + if (!system) + return_VALUE(-ENOMEM); + memset(system, 0, sizeof(struct acpi_system)); + + system->handle = device->handle; + sprintf(acpi_device_name(device), "%s", ACPI_SYSTEM_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_SYSTEM_CLASS); + acpi_driver_data(device) = system; + + result = acpi_system_add_fs(device); + if (result) + goto end; + + printk(KERN_INFO PREFIX "%s [%s] (supports", + acpi_device_name(device), acpi_device_bid(device)); + for (i=0; istates[i] = 1; + printk(" S%d", i); + } + } + printk(")\n"); + +#ifdef CONFIG_PM + /* Install the soft-off (S5) handler. */ + if (system->states[ACPI_STATE_S5]) { + pm_power_off = acpi_power_off; + register_sysrq_key('o', &sysrq_acpi_poweroff_op); + + /* workaround: some systems don't claim S4 support, but they + do support S5 (power-down). That is all we need, so + indicate support. */ + system->states[ACPI_STATE_S4] = 1; + } +#endif + +end: + if (result) + kfree(system); + + return_VALUE(result); +} + + +static int +acpi_system_remove ( + struct acpi_device *device, + int type) +{ + struct acpi_system *system = NULL; + + ACPI_FUNCTION_TRACE("acpi_system_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + system = (struct acpi_system *) acpi_driver_data(device); + +#ifdef CONFIG_PM + /* Remove the soft-off (S5) handler. */ + if (system->states[ACPI_STATE_S5]) { + unregister_sysrq_key('o', &sysrq_acpi_poweroff_op); + pm_power_off = NULL; + } +#endif + + acpi_system_remove_fs(device); + + kfree(system); + + return 0; +} + + +int __init +acpi_system_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_system_init"); + + result = acpi_bus_register_driver(&acpi_system_driver); + if (result < 0) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + + +void __exit +acpi_system_exit (void) +{ + ACPI_FUNCTION_TRACE("acpi_system_exit"); + acpi_bus_unregister_driver(&acpi_system_driver); + return_VOID; +} diff -Nru a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c --- a/drivers/acpi/tables/tbconvrt.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/tables/tbconvrt.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbconvrt - ACPI Table conversion utilities - * $Revision: 36 $ + * $Revision: 41 $ * *****************************************************************************/ @@ -55,7 +55,7 @@ ACPI_FUNCTION_ENTRY (); -#ifndef _IA64 +#if ACPI_MACHINE_WIDTH != 64 if (RSDP->revision < 2) { pointer_size = sizeof (u32); @@ -93,7 +93,7 @@ acpi_table_desc *table_info, u32 *number_of_tables) { - u32 table_size; + ACPI_SIZE table_size; u32 i; xsdt_descriptor *new_table; @@ -107,7 +107,7 @@ /* Compute size of the converted XSDT */ - table_size = (*number_of_tables * sizeof (u64)) + sizeof (acpi_table_header); + table_size = ((ACPI_SIZE) *number_of_tables * sizeof (u64)) + sizeof (acpi_table_header); /* Allocate an XSDT */ @@ -119,7 +119,7 @@ /* Copy the header and set the length */ ACPI_MEMCPY (new_table, table_info->pointer, sizeof (acpi_table_header)); - new_table->header.length = table_size; + new_table->header.length = (u32) table_size; /* Copy the table pointers */ @@ -151,6 +151,165 @@ /******************************************************************************* * + * FUNCTION: Acpi_tb_convert_fadt1 + * + * PARAMETERS: Local_fadt - Pointer to new FADT + * Original_fadt - Pointer to old FADT + * + * RETURN: Populates Local_fadt + * + * DESCRIPTION: Convert an ACPI 1.0 FADT to common internal format + * + ******************************************************************************/ + +static void +acpi_tb_convert_fadt1 ( + fadt_descriptor_rev2 *local_fadt, + fadt_descriptor_rev1 *original_fadt) +{ + + + /* ACPI 1.0 FACS */ + /* The BIOS stored FADT should agree with Revision 1.0 */ + + /* + * Copy the table header and the common part of the tables. + * + * The 2.0 table is an extension of the 1.0 table, so the entire 1.0 + * table can be copied first, then expand some fields to 64 bits. + */ + ACPI_MEMCPY (local_fadt, original_fadt, sizeof (fadt_descriptor_rev1)); + + /* Convert table pointers to 64-bit fields */ + + ACPI_STORE_ADDRESS (local_fadt->Xfirmware_ctrl, local_fadt->V1_firmware_ctrl); + ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt); + + /* + * System Interrupt Model isn't used in ACPI 2.0 (Local_fadt->Reserved1 = 0;) + */ + + /* + * This field is set by the OEM to convey the preferred power management + * profile to OSPM. It doesn't have any 1.0 equivalence. Since we don't + * know what kind of 32-bit system this is, we will use "unspecified". + */ + local_fadt->prefer_PM_profile = PM_UNSPECIFIED; + + /* + * Processor Performance State Control. This is the value OSPM writes to + * the SMI_CMD register to assume processor performance state control + * responsibility. There isn't any equivalence in 1.0, leave it zeroed. + */ + local_fadt->pstate_cnt = 0; + + /* + * Support for the _CST object and C States change notification. + * This data item hasn't any 1.0 equivalence so leave it zero. + */ + local_fadt->cst_cnt = 0; + + /* + * Since there isn't any equivalence in 1.0 and since it highly likely + * that a 1.0 system has legacy support. + */ + local_fadt->iapc_boot_arch = BAF_LEGACY_DEVICES; + + /* + * Convert the V1.0 block addresses to V2.0 GAS structures + */ + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xpm1a_evt_blk, local_fadt->pm1_evt_len, local_fadt->V1_pm1a_evt_blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xpm1b_evt_blk, local_fadt->pm1_evt_len, local_fadt->V1_pm1b_evt_blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xpm1a_cnt_blk, local_fadt->pm1_cnt_len, local_fadt->V1_pm1a_cnt_blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xpm1b_cnt_blk, local_fadt->pm1_cnt_len, local_fadt->V1_pm1b_cnt_blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xpm2_cnt_blk, local_fadt->pm2_cnt_len, local_fadt->V1_pm2_cnt_blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xpm_tmr_blk, local_fadt->pm_tm_len, local_fadt->V1_pm_tmr_blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xgpe0_blk, local_fadt->gpe0_blk_len, local_fadt->V1_gpe0_blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xgpe1_blk, local_fadt->gpe1_blk_len, local_fadt->V1_gpe1_blk); + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_convert_fadt2 + * + * PARAMETERS: Local_fadt - Pointer to new FADT + * Original_fadt - Pointer to old FADT + * + * RETURN: Populates Local_fadt + * + * DESCRIPTION: Convert an ACPI 2.0 FADT to common internal format. + * Handles optional "X" fields. + * + ******************************************************************************/ + +static void +acpi_tb_convert_fadt2 ( + fadt_descriptor_rev2 *local_fadt, + fadt_descriptor_rev2 *original_fadt) +{ + + /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */ + + ACPI_MEMCPY (local_fadt, original_fadt, sizeof (fadt_descriptor_rev2)); + + /* + * "X" fields are optional extensions to the original V1.0 fields, so + * we must selectively expand V1.0 fields if the corresponding X field + * is zero. + */ + if (!(ACPI_GET_ADDRESS (local_fadt->Xfirmware_ctrl))) { + ACPI_STORE_ADDRESS (local_fadt->Xfirmware_ctrl, local_fadt->V1_firmware_ctrl); + } + + if (!(ACPI_GET_ADDRESS (local_fadt->Xdsdt))) { + ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt); + } + + if (!(ACPI_GET_ADDRESS (local_fadt->Xpm1a_evt_blk.address))) { + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xpm1a_evt_blk, + local_fadt->pm1_evt_len, local_fadt->V1_pm1a_evt_blk); + } + + if (!(ACPI_GET_ADDRESS (local_fadt->Xpm1b_evt_blk.address))) { + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xpm1b_evt_blk, + local_fadt->pm1_evt_len, local_fadt->V1_pm1b_evt_blk); + } + + if (!(ACPI_GET_ADDRESS (local_fadt->Xpm1a_cnt_blk.address))) { + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xpm1a_cnt_blk, + local_fadt->pm1_cnt_len, local_fadt->V1_pm1a_cnt_blk); + } + + if (!(ACPI_GET_ADDRESS (local_fadt->Xpm1b_cnt_blk.address))) { + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xpm1b_cnt_blk, + local_fadt->pm1_cnt_len, local_fadt->V1_pm1b_cnt_blk); + } + + if (!(ACPI_GET_ADDRESS (local_fadt->Xpm2_cnt_blk.address))) { + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xpm2_cnt_blk, + local_fadt->pm2_cnt_len, local_fadt->V1_pm2_cnt_blk); + } + + if (!(ACPI_GET_ADDRESS (local_fadt->Xpm_tmr_blk.address))) { + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xpm_tmr_blk, + local_fadt->pm_tm_len, local_fadt->V1_pm_tmr_blk); + } + + if (!(ACPI_GET_ADDRESS (local_fadt->Xgpe0_blk.address))) { + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xgpe0_blk, + local_fadt->gpe0_blk_len, local_fadt->V1_gpe0_blk); + } + + if (!(ACPI_GET_ADDRESS (local_fadt->Xgpe1_blk.address))) { + ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->Xgpe1_blk, + local_fadt->gpe1_blk_len, local_fadt->V1_gpe1_blk); + } +} + +/******************************************************************************* + * * FUNCTION: Acpi_tb_convert_table_fadt * * PARAMETERS: None @@ -170,8 +329,7 @@ acpi_status acpi_tb_convert_table_fadt (void) { - fadt_descriptor_rev1 *FADT1; - fadt_descriptor_rev2 *FADT2; + fadt_descriptor_rev2 *local_fadt; acpi_table_desc *table_desc; @@ -182,97 +340,45 @@ * Acpi_gbl_FADT is valid * Allocate and zero the 2.0 FADT buffer */ - FADT2 = ACPI_MEM_CALLOCATE (sizeof (fadt_descriptor_rev2)); - if (FADT2 == NULL) { + local_fadt = ACPI_MEM_CALLOCATE (sizeof (fadt_descriptor_rev2)); + if (local_fadt == NULL) { return_ACPI_STATUS (AE_NO_MEMORY); } /* - * The ACPI FADT revision number is FADT2_REVISION_ID=3 - * So, if the current table revision is less than 3 it is type 1.0 + * FADT length and version validation. The table must be at least as + * long as the version 1.0 FADT */ + if (acpi_gbl_FADT->header.length < sizeof (fadt_descriptor_rev1)) { + ACPI_REPORT_ERROR (("Invalid FADT table length: 0x%X\n", acpi_gbl_FADT->header.length)); + return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); + } + if (acpi_gbl_FADT->header.revision >= FADT2_REVISION_ID) { - /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */ + if (acpi_gbl_FADT->header.length < sizeof (fadt_descriptor_rev2)) { + /* Length is too short to be a V2.0 table */ - *FADT2 = *((fadt_descriptor_rev2*) acpi_gbl_FADT); - } - else { - /* ACPI 1.0 FACS */ + ACPI_REPORT_WARNING (("Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n", + acpi_gbl_FADT->header.length, acpi_gbl_FADT->header.revision)); - /* The BIOS stored FADT should agree with Revision 1.0 */ + acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT); + } + else { + /* Valid V2.0 table */ - FADT1 = (fadt_descriptor_rev1*) acpi_gbl_FADT; + acpi_tb_convert_fadt2 (local_fadt, acpi_gbl_FADT); + } + } + else { + /* Valid V1.0 table */ - /* - * Copy the table header and the common part of the tables. - * - * The 2.0 table is an extension of the 1.0 table, so the entire 1.0 - * table can be copied first, then expand some fields to 64 bits. - */ - ACPI_MEMCPY (FADT2, FADT1, sizeof (fadt_descriptor_rev1)); - - /* Convert table pointers to 64-bit fields */ - - ACPI_STORE_ADDRESS (FADT2->Xfirmware_ctrl, FADT1->firmware_ctrl); - ACPI_STORE_ADDRESS (FADT2->Xdsdt, FADT1->dsdt); - - /* - * System Interrupt Model isn't used in ACPI 2.0 (FADT2->Reserved1 = 0;) - */ - - /* - * This field is set by the OEM to convey the preferred power management - * profile to OSPM. It doesn't have any 1.0 equivalence. Since we don't - * know what kind of 32-bit system this is, we will use "unspecified". - */ - FADT2->prefer_PM_profile = PM_UNSPECIFIED; - - /* - * Processor Performance State Control. This is the value OSPM writes to - * the SMI_CMD register to assume processor performance state control - * responsibility. There isn't any equivalence in 1.0, leave it zeroed. - */ - FADT2->pstate_cnt = 0; - - /* - * Support for the _CST object and C States change notification. - * This data item hasn't any 1.0 equivalence so leave it zero. - */ - FADT2->cst_cnt = 0; - - /* - * Since there isn't any equivalence in 1.0 and since it highly likely - * that a 1.0 system has legacy support. - */ - FADT2->iapc_boot_arch = BAF_LEGACY_DEVICES; - - /* - * Convert the V1.0 block addresses to V2.0 GAS structures - * in this order: - * - * PM 1_a Events - * PM 1_b Events - * PM 1_a Control - * PM 1_b Control - * PM 2 Control - * PM Timer Control - * GPE Block 0 - * GPE Block 1 - */ - ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm1a_evt_blk, FADT1->pm1_evt_len, FADT1->pm1a_evt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm1b_evt_blk, FADT1->pm1_evt_len, FADT1->pm1b_evt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm1a_cnt_blk, FADT1->pm1_cnt_len, FADT1->pm1a_cnt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm1b_cnt_blk, FADT1->pm1_cnt_len, FADT1->pm1b_cnt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm2_cnt_blk, FADT1->pm2_cnt_len, FADT1->pm2_cnt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm_tmr_blk, FADT1->pm_tm_len, FADT1->pm_tmr_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xgpe0_blk, FADT1->gpe0_blk_len, FADT1->gpe0_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xgpe1_blk, FADT1->gpe1_blk_len, FADT1->gpe1_blk); + acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT); } /* - * Global FADT pointer will point to the common V2.0 FADT + * Global FADT pointer will point to the new common V2.0 FADT */ - acpi_gbl_FADT = FADT2; + acpi_gbl_FADT = local_fadt; acpi_gbl_FADT->header.length = sizeof (FADT_DESCRIPTOR); /* Free the original table */ @@ -282,10 +388,10 @@ /* Install the new table */ - table_desc->pointer = (acpi_table_header *) acpi_gbl_FADT; + table_desc->pointer = (acpi_table_header *) acpi_gbl_FADT; table_desc->base_pointer = acpi_gbl_FADT; - table_desc->allocation = ACPI_MEM_ALLOCATED; - table_desc->length = sizeof (fadt_descriptor_rev2); + table_desc->allocation = ACPI_MEM_ALLOCATED; + table_desc->length = sizeof (fadt_descriptor_rev2); /* Dump the entire FADT */ @@ -315,35 +421,42 @@ acpi_tb_build_common_facs ( acpi_table_desc *table_info) { - facs_descriptor_rev1 *FACS1; - facs_descriptor_rev2 *FACS2; - ACPI_FUNCTION_TRACE ("Tb_build_common_facs"); + /* Absolute minimum length is 24, but the ACPI spec says 64 */ + + if (acpi_gbl_FACS->length < 24) { + ACPI_REPORT_ERROR (("Invalid FACS table length: 0x%X\n", acpi_gbl_FACS->length)); + return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); + } + + if (acpi_gbl_FACS->length < 64) { + ACPI_REPORT_WARNING (("FACS is shorter than the ACPI specification allows: 0x%X, using anyway\n", + acpi_gbl_FACS->length)); + } + /* Copy fields to the new FACS */ - if (acpi_gbl_RSDP->revision < 2) { - /* ACPI 1.0 FACS */ + acpi_gbl_common_fACS.global_lock = &(acpi_gbl_FACS->global_lock); - FACS1 = (facs_descriptor_rev1 *) acpi_gbl_FACS; + if ((acpi_gbl_RSDP->revision < 2) || + (acpi_gbl_FACS->length < 32) || + (!(ACPI_GET_ADDRESS (acpi_gbl_FACS->Xfirmware_waking_vector)))) { + /* ACPI 1.0 FACS or short table or optional X_ field is zero */ - acpi_gbl_common_fACS.global_lock = &(FACS1->global_lock); - acpi_gbl_common_fACS.firmware_waking_vector = (u64 *) &FACS1->firmware_waking_vector; + acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR (u64, &(acpi_gbl_FACS->firmware_waking_vector)); acpi_gbl_common_fACS.vector_width = 32; } else { - /* ACPI 2.0 FACS */ + /* ACPI 2.0 FACS with valid X_ field */ - FACS2 = (facs_descriptor_rev2 *) acpi_gbl_FACS; - - acpi_gbl_common_fACS.global_lock = &(FACS2->global_lock); - acpi_gbl_common_fACS.firmware_waking_vector = &FACS2->Xfirmware_waking_vector; + acpi_gbl_common_fACS.firmware_waking_vector = &acpi_gbl_FACS->Xfirmware_waking_vector; acpi_gbl_common_fACS.vector_width = 64; } - return_ACPI_STATUS (AE_OK); + return_ACPI_STATUS (AE_OK); } diff -Nru a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c --- a/drivers/acpi/tables/tbget.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/tables/tbget.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbget - ACPI Table get* routines - * $Revision: 67 $ + * $Revision: 77 $ * *****************************************************************************/ @@ -34,6 +34,123 @@ /******************************************************************************* * + * FUNCTION: Acpi_tb_table_override + * + * PARAMETERS: *Table_info - Info for current table + * + * RETURN: None + * + * DESCRIPTION: Attempts override of current table with a new one if provided + * by the host OS. + * + ******************************************************************************/ + +void +acpi_tb_table_override ( + acpi_table_desc *table_info) +{ + acpi_table_header *new_table; + acpi_status status; + ACPI_POINTER address; + acpi_table_desc new_table_info; + + + ACPI_FUNCTION_TRACE ("Acpi_tb_table_override"); + + + status = acpi_os_table_override (table_info->pointer, &new_table); + if (ACPI_FAILURE (status)) { + /* Some severe error from the OSL, but we basically ignore it */ + + ACPI_REPORT_ERROR (("Could not override ACPI table, %s\n", + acpi_format_exception (status))); + return_VOID; + } + + if (!new_table) { + /* No table override */ + + return_VOID; + } + + /* + * We have a new table to override the old one. Get a copy of + * the new one. We know that the new table has a logical pointer. + */ + address.pointer_type = ACPI_LOGICAL_POINTER; + address.pointer.logical = new_table; + + status = acpi_tb_get_table (&address, &new_table_info); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not copy ACPI table override\n")); + return_VOID; + } + + /* + * Delete the original table + */ + acpi_tb_delete_single_table (table_info); + + /* Copy the table info */ + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Successful table override [%4.4s]\n", + ((acpi_table_header *) new_table_info.pointer)->signature)); + + ACPI_MEMCPY (table_info, &new_table_info, sizeof (acpi_table_desc)); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_get_table_with_override + * + * PARAMETERS: Address - Physical or logical address of table + * *Table_info - Where the table info is returned + * + * RETURN: Status + * + * DESCRIPTION: Gets and installs the table with possible table override by OS. + * + ******************************************************************************/ + +acpi_status +acpi_tb_get_table_with_override ( + ACPI_POINTER *address, + acpi_table_desc *table_info) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("Acpi_tb_get_table_with_override"); + + + status = acpi_tb_get_table (address, table_info); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not get ACPI table, %s\n", + acpi_format_exception (status))); + return_ACPI_STATUS (status); + } + + /* + * Attempt override. It either happens or it doesn't, no status + */ + acpi_tb_table_override (table_info); + + /* Install the table */ + + status = acpi_tb_install_table (table_info); + if (ACPI_FAILURE (status)) { + ACPI_REPORT_ERROR (("Could not install ACPI table, %s\n", + acpi_format_exception (status))); + } + + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * * FUNCTION: Acpi_tb_get_table_ptr * * PARAMETERS: Table_type - one of the defined table types @@ -112,10 +229,8 @@ * * FUNCTION: Acpi_tb_get_table * - * PARAMETERS: Physical_address - Physical address of table to retrieve - * *Buffer_ptr - If Buffer_ptr is valid, read data from - * buffer rather than searching memory - * *Table_info - Where the table info is returned + * PARAMETERS: Address - Physical address of table to retrieve + * *Table_info - Where the table info is returned * * RETURN: Status * @@ -130,7 +245,7 @@ { acpi_table_header *table_header = NULL; acpi_table_header *full_table = NULL; - u32 size; + ACPI_SIZE size; u8 allocation; acpi_status status = AE_OK; @@ -159,7 +274,7 @@ /* Copy the entire table (including header) to the local buffer */ - size = table_header->length; + size = (ACPI_SIZE) table_header->length; ACPI_MEMCPY (full_table, table_header, size); /* Save allocation type */ @@ -213,7 +328,6 @@ * FUNCTION: Acpi_tb_get_all_tables * * PARAMETERS: Number_of_tables - Number of tables to get - * Table_ptr - Input buffer pointer, optional * * RETURN: Status * @@ -230,8 +344,7 @@ acpi_status acpi_tb_get_all_tables ( - u32 number_of_tables, - acpi_table_header *table_ptr) + u32 number_of_tables) { acpi_status status = AE_OK; u32 index; @@ -268,18 +381,23 @@ /* Recognize and install the table */ - status = acpi_tb_install_table (table_ptr, &table_info); + status = acpi_tb_install_table (&table_info); if (ACPI_FAILURE (status)) { /* * Unrecognized or unsupported table, delete it and ignore the * error. Just get as many tables as we can, later we will * determine if there are enough tables to continue. */ - acpi_tb_uninstall_table (&table_info); + (void) acpi_tb_uninstall_table (&table_info); status = AE_OK; } } + if (!acpi_gbl_FADT) { + ACPI_REPORT_ERROR (("No FADT present in R/XSDT\n")); + return_ACPI_STATUS (AE_NO_ACPI_TABLES); + } + /* * Convert the FADT to a common format. This allows earlier revisions of the * table to coexist with newer versions, using common access code. @@ -299,15 +417,17 @@ status = acpi_tb_get_table (&address, &table_info); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("Could not get the FACS\n")); + ACPI_REPORT_ERROR (("Could not get the FACS, %s\n", + acpi_format_exception (status))); return_ACPI_STATUS (status); } /* Install the FACS */ - status = acpi_tb_install_table (table_ptr, &table_info); + status = acpi_tb_install_table (&table_info); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("Could not install the FACS\n")); + ACPI_REPORT_ERROR (("Could not install the FACS, %s\n", + acpi_format_exception (status))); return_ACPI_STATUS (status); } @@ -317,35 +437,30 @@ */ status = acpi_tb_build_common_facs (&table_info); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("Could not convert FACS to common internal format\n")); return_ACPI_STATUS (status); } /* - * Get the DSDT (We know that the FADT is valid now) + * Get/install the DSDT (We know that the FADT is valid now) */ address.pointer_type = acpi_gbl_table_flags; address.pointer.value = ACPI_GET_ADDRESS (acpi_gbl_FADT->Xdsdt); - status = acpi_tb_get_table (&address, &table_info); + status = acpi_tb_get_table_with_override (&address, &table_info); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("Could not get the DSDT\n")); return_ACPI_STATUS (status); } - /* Install the DSDT */ + /* Set Integer Width (32/64) based upon DSDT revision */ - status = acpi_tb_install_table (table_ptr, &table_info); - if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("Could not install the DSDT\n")); - return_ACPI_STATUS (status); - } + acpi_ut_set_integer_width (acpi_gbl_DSDT->revision); /* Dump the entire DSDT */ ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, - "Hex dump of entire DSDT, size %d (0x%X)\n", - acpi_gbl_DSDT->length, acpi_gbl_DSDT->length)); + "Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n", + acpi_gbl_DSDT->length, acpi_gbl_DSDT->length, acpi_gbl_integer_bit_width)); ACPI_DUMP_BUFFER ((u8 *) acpi_gbl_DSDT, acpi_gbl_DSDT->length); /* Always delete the RSDP mapping, we are done with it */ @@ -428,7 +543,7 @@ /* The RSDP supplied is OK */ - table_info.pointer = (acpi_table_header *) rsdp; + table_info.pointer = ACPI_CAST_PTR (acpi_table_header, rsdp); table_info.length = sizeof (RSDP_DESCRIPTOR); table_info.allocation = ACPI_MEM_MAPPED; table_info.base_pointer = rsdp; @@ -442,7 +557,7 @@ /* Save the RSDP in a global for easy access */ - acpi_gbl_RSDP = (RSDP_DESCRIPTOR *) table_info.pointer; + acpi_gbl_RSDP = ACPI_CAST_PTR (RSDP_DESCRIPTOR, table_info.pointer); return_ACPI_STATUS (status); @@ -508,7 +623,7 @@ acpi_tb_validate_rsdt ( acpi_table_header *table_ptr) { - u32 no_match; + int no_match; ACPI_FUNCTION_NAME ("Tb_validate_rsdt"); @@ -535,8 +650,9 @@ ACPI_DUMP_BUFFER (acpi_gbl_RSDP, 20); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, - "RSDT/XSDT signature at %X is invalid\n", - acpi_gbl_RSDP->rsdt_physical_address)); + "RSDT/XSDT signature at %X (%p) is invalid\n", + acpi_gbl_RSDP->rsdt_physical_address, + (void *) (NATIVE_UINT) acpi_gbl_RSDP->rsdt_physical_address)); return (AE_BAD_SIGNATURE); } @@ -563,7 +679,7 @@ acpi_tb_get_table_pointer ( ACPI_POINTER *address, u32 flags, - u32 *size, + ACPI_SIZE *size, acpi_table_header **table_ptr) { acpi_status status = AE_OK; @@ -590,6 +706,9 @@ *table_ptr = address->pointer.logical; *size = 0; break; + + default: + return (AE_BAD_PARAMETER); } } else { @@ -605,6 +724,9 @@ status = AE_BAD_PARAMETER; break; + + default: + return (AE_BAD_PARAMETER); } } @@ -636,25 +758,21 @@ ACPI_FUNCTION_TRACE ("Tb_get_table_rsdt"); - /* - * Get the RSDT from the RSDP - */ - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", - acpi_gbl_RSDP, - ACPI_HIDWORD (acpi_gbl_RSDP->rsdt_physical_address), - ACPI_LODWORD (acpi_gbl_RSDP->rsdt_physical_address))); - - - /* Get the RSDT/XSDT */ + /* Get the RSDT/XSDT from the RSDP */ acpi_tb_get_rsdt_address (&address); status = acpi_tb_get_table (&address, &table_info); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not get the RSDT, %s\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not get the R/XSDT, %s\n", acpi_format_exception (status))); return_ACPI_STATUS (status); } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", + acpi_gbl_RSDP, + ACPI_HIDWORD (address.pointer.value), + ACPI_LODWORD (address.pointer.value))); /* Check the RSDT or XSDT signature */ diff -Nru a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c --- a/drivers/acpi/tables/tbinstal.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/tables/tbinstal.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbinstal - ACPI table installation and removal - * $Revision: 57 $ + * $Revision: 61 $ * *****************************************************************************/ @@ -84,8 +84,7 @@ * * FUNCTION: Acpi_tb_install_table * - * PARAMETERS: Table_ptr - Input buffer pointer, optional - * Table_info - Return value from Acpi_tb_get_table + * PARAMETERS: Table_info - Return value from Acpi_tb_get_table * * RETURN: Status * @@ -97,7 +96,6 @@ acpi_status acpi_tb_install_table ( - acpi_table_header *table_ptr, acpi_table_desc *table_info) { acpi_status status; @@ -109,7 +107,7 @@ * Check the table signature and make sure it is recognized * Also checks the header checksum */ - status = acpi_tb_recognize_table (table_ptr, table_info); + status = acpi_tb_recognize_table (table_info); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -137,8 +135,7 @@ * * FUNCTION: Acpi_tb_recognize_table * - * PARAMETERS: Table_ptr - Input buffer pointer, optional - * Table_info - Return value from Acpi_tb_get_table + * PARAMETERS: Table_info - Return value from Acpi_tb_get_table * * RETURN: Status * @@ -156,7 +153,6 @@ acpi_status acpi_tb_recognize_table ( - acpi_table_header *table_ptr, acpi_table_desc *table_info) { acpi_table_header *table_header; @@ -193,7 +189,7 @@ /* Return the table type and length via the info struct */ - table_info->length = table_header->length; + table_info->length = (ACPI_SIZE) table_header->length; /* * Validate checksum for _most_ tables, @@ -201,12 +197,14 @@ */ if (table_info->type != ACPI_TABLE_FACS) { status = acpi_tb_verify_table_checksum (table_header); - if (ACPI_FAILURE (status) && - (!ACPI_CHECKSUM_ABORT)) { + +#if (!ACPI_CHECKSUM_ABORT) + if (ACPI_FAILURE (status)) { /* Ignore the error if configuration says so */ status = AE_OK; } +#endif } return_ACPI_STATUS (status); @@ -497,6 +495,9 @@ acpi_os_unmap_memory (table_desc->base_pointer, table_desc->length); break; + + default: + break; } } } @@ -508,7 +509,7 @@ * * PARAMETERS: Table_info - A table info struct * - * RETURN: None. + * RETURN: Pointer to the next table in the list (of same type) * * DESCRIPTION: Free the memory associated with an internal ACPI table that * is either installed or has never been installed. @@ -523,7 +524,7 @@ acpi_table_desc *next_desc; - ACPI_FUNCTION_TRACE_PTR ("Tb_delete_single_table", table_desc); + ACPI_FUNCTION_TRACE_PTR ("Acpi_tb_uninstall_table", table_desc); if (!table_desc) { diff -Nru a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c --- a/drivers/acpi/tables/tbutils.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/tables/tbutils.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbutils - Table manipulation utilities - * $Revision: 51 $ + * $Revision: 53 $ * *****************************************************************************/ @@ -26,7 +26,6 @@ #include "acpi.h" #include "actables.h" -#include "acinterp.h" #define _COMPONENT ACPI_TABLES @@ -116,7 +115,7 @@ /* Ensure that the signature is 4 ASCII characters */ - ACPI_MOVE_UNALIGNED32_TO_32 (&signature, &table_header->signature); + ACPI_MOVE_UNALIGNED32_TO_32 (&signature, table_header->signature); if (!acpi_ut_valid_acpi_name (signature)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Table signature at %p [%p] has invalid characters\n", @@ -162,11 +161,11 @@ acpi_status acpi_tb_map_acpi_table ( ACPI_PHYSICAL_ADDRESS physical_address, - u32 *size, + ACPI_SIZE *size, acpi_table_header **logical_address) { acpi_table_header *table; - u32 table_size = *size; + ACPI_SIZE table_size = *size; acpi_status status = AE_OK; @@ -186,7 +185,7 @@ /* Extract the full table length before we delete the mapping */ - table_size = table->length; + table_size = (ACPI_SIZE) table->length; /* * Validate the header and delete the mapping. @@ -255,7 +254,7 @@ if (checksum) { ACPI_REPORT_WARNING (("Invalid checksum (%X) in table %4.4s\n", - checksum, (char *) &table_header->signature)); + checksum, table_header->signature)); status = AE_BAD_CHECKSUM; } diff -Nru a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c --- a/drivers/acpi/tables/tbxface.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/tables/tbxface.c Sun Jun 2 18:44:58 2002 @@ -2,7 +2,7 @@ * * Module Name: tbxface - Public interfaces to the ACPI subsystem * ACPI table oriented interfaces - * $Revision: 52 $ + * $Revision: 57 $ * *****************************************************************************/ @@ -27,7 +27,6 @@ #include "acpi.h" #include "acnamesp.h" -#include "acinterp.h" #include "actables.h" @@ -91,7 +90,7 @@ /* Now get the rest of the tables */ - status = acpi_tb_get_all_tables (number_of_tables, NULL); + status = acpi_tb_get_all_tables (number_of_tables); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("Acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n", acpi_format_exception (status))); @@ -165,7 +164,7 @@ /* Install the new table into the local data structures */ - status = acpi_tb_install_table (NULL, &table_info); + status = acpi_tb_install_table (&table_info); if (ACPI_FAILURE (status)) { /* Free table allocated by Acpi_tb_get_table */ @@ -196,7 +195,7 @@ if (ACPI_FAILURE (status)) { /* Uninstall table and free the buffer */ - acpi_tb_uninstall_table (table_info.installed_desc); + (void) acpi_tb_uninstall_table (table_info.installed_desc); } return_ACPI_STATUS (status); @@ -358,7 +357,7 @@ { acpi_table_header *tbl_ptr; acpi_status status; - u32 table_length; + ACPI_SIZE table_length; ACPI_FUNCTION_TRACE ("Acpi_get_table"); @@ -408,7 +407,7 @@ table_length = sizeof (RSDP_DESCRIPTOR); } else { - table_length = tbl_ptr->length; + table_length = (ACPI_SIZE) tbl_ptr->length; } /* Validate/Allocate/Clear caller buffer */ diff -Nru a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c --- a/drivers/acpi/tables/tbxfroot.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/tables/tbxfroot.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbxfroot - Find the root ACPI table (RSDT) - * $Revision: 61 $ + * $Revision: 63 $ * *****************************************************************************/ @@ -123,8 +123,8 @@ acpi_table_header *rsdt_ptr = NULL; acpi_table_header *table_ptr; acpi_status status; - u32 rsdt_size = 0; - u32 table_size; + ACPI_SIZE rsdt_size = 0; + ACPI_SIZE table_size; u32 table_count; u32 i; u32 j; @@ -187,16 +187,16 @@ } } - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", - acpi_gbl_RSDP, - ACPI_HIDWORD (acpi_gbl_RSDP->rsdt_physical_address), - ACPI_LODWORD (acpi_gbl_RSDP->rsdt_physical_address))); - /* Get the RSDT and validate it */ acpi_tb_get_rsdt_address (&address); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", + acpi_gbl_RSDP, + ACPI_HIDWORD (address.pointer.value), + ACPI_LODWORD (address.pointer.value))); + status = acpi_tb_get_table_pointer (&address, flags, &rsdt_size, &rsdt_ptr); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); @@ -272,7 +272,7 @@ /* TBD: Move to a new file */ -#ifndef _IA16 +#if ACPI_MACHINE_WIDTH != 16 /******************************************************************************* * @@ -417,7 +417,7 @@ /* Found it, return the physical address */ phys_addr = LO_RSDP_WINDOW_BASE; - phys_addr += (mem_rover - table_ptr); + phys_addr += ACPI_PTR_DIFF (mem_rover,table_ptr); table_info->physical_address = phys_addr; return_ACPI_STATUS (AE_OK); @@ -439,7 +439,7 @@ /* Found it, return the physical address */ phys_addr = HI_RSDP_WINDOW_BASE; - phys_addr += (mem_rover - table_ptr); + phys_addr += ACPI_PTR_DIFF (mem_rover, table_ptr); table_info->physical_address = phys_addr; return_ACPI_STATUS (AE_OK); diff -Nru a/drivers/acpi/tables.c b/drivers/acpi/tables.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/tables.c Sun Jun 2 18:44:57 2002 @@ -0,0 +1,475 @@ +/* + * acpi_tables.c - ACPI Boot-Time Table Parsing + * + * Copyright (C) 2001 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PREFIX "ACPI: " + +#define ACPI_MAX_TABLES ACPI_TABLE_COUNT + +static char *acpi_table_signatures[ACPI_TABLE_COUNT] = { + [ACPI_TABLE_UNKNOWN] = "????", + [ACPI_APIC] = "APIC", + [ACPI_BOOT] = "BOOT", + [ACPI_DBGP] = "DBGP", + [ACPI_DSDT] = "DSDT", + [ACPI_ECDT] = "ECDT", + [ACPI_ETDT] = "ETDT", + [ACPI_FACP] = "FACP", + [ACPI_FACS] = "FACS", + [ACPI_OEMX] = "OEM", + [ACPI_PSDT] = "PSDT", + [ACPI_SBST] = "SBST", + [ACPI_SLIT] = "SLIT", + [ACPI_SPCR] = "SPCR", + [ACPI_SRAT] = "SRAT", + [ACPI_SSDT] = "SSDT", + [ACPI_SPMI] = "SPMI" +}; + +/* System Description Table (RSDT/XSDT) */ +struct acpi_table_sdt { + unsigned long pa; /* Physical Address */ + unsigned long count; /* Table count */ + struct { + unsigned long pa; + enum acpi_table_id id; + unsigned long size; + } entry[ACPI_MAX_TABLES]; +} __attribute__ ((packed)); + +static struct acpi_table_sdt sdt; + +acpi_madt_entry_handler madt_handlers[ACPI_MADT_ENTRY_COUNT]; + + +void +acpi_table_print ( + struct acpi_table_header *header, + unsigned long phys_addr) +{ + char *name = NULL; + + if (!header) + return; + + /* Some table signatures aren't good table names */ + + if (!strncmp((char *) &header->signature, + acpi_table_signatures[ACPI_APIC], + sizeof(header->signature))) { + name = "MADT"; + } + else if (!strncmp((char *) &header->signature, + acpi_table_signatures[ACPI_FACP], + sizeof(header->signature))) { + name = "FADT"; + } + else + name = header->signature; + + printk(KERN_INFO PREFIX "%.4s (v%3.3d %6.6s %8.8s %5.5d.%5.5d) @ 0x%p\n", + name, header->revision, header->oem_id, + header->oem_table_id, header->oem_revision >> 16, + header->oem_revision & 0xffff, (void *) phys_addr); +} + + +void +acpi_table_print_madt_entry ( + acpi_table_entry_header *header) +{ + if (!header) + return; + + switch (header->type) { + + case ACPI_MADT_LAPIC: + { + struct acpi_table_lapic *p = + (struct acpi_table_lapic*) header; + printk(KERN_INFO PREFIX "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n", + p->acpi_id, p->id, p->flags.enabled?"enabled":"disabled"); + } + break; + + case ACPI_MADT_IOAPIC: + { + struct acpi_table_ioapic *p = + (struct acpi_table_ioapic*) header; + printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] global_irq_base[0x%x])\n", + p->id, p->address, p->global_irq_base); + } + break; + + case ACPI_MADT_INT_SRC_OVR: + { + struct acpi_table_int_src_ovr *p = + (struct acpi_table_int_src_ovr*) header; + printk(KERN_INFO PREFIX "INT_SRC_OVR (bus[%d] irq[0x%x] global_irq[0x%x] polarity[0x%x] trigger[0x%x])\n", + p->bus, p->bus_irq, p->global_irq, p->flags.polarity, p->flags.trigger); + } + break; + + case ACPI_MADT_NMI_SRC: + { + struct acpi_table_nmi_src *p = + (struct acpi_table_nmi_src*) header; + printk(KERN_INFO PREFIX "NMI_SRC (polarity[0x%x] trigger[0x%x] global_irq[0x%x])\n", + p->flags.polarity, p->flags.trigger, p->global_irq); + } + break; + + case ACPI_MADT_LAPIC_NMI: + { + struct acpi_table_lapic_nmi *p = + (struct acpi_table_lapic_nmi*) header; + printk(KERN_INFO PREFIX "LAPIC_NMI (acpi_id[0x%02x] polarity[0x%x] trigger[0x%x] lint[0x%x])\n", + p->acpi_id, p->flags.polarity, p->flags.trigger, p->lint); + } + break; + + case ACPI_MADT_LAPIC_ADDR_OVR: + { + struct acpi_table_lapic_addr_ovr *p = + (struct acpi_table_lapic_addr_ovr*) header; + printk(KERN_INFO PREFIX "LAPIC_ADDR_OVR (address[%p])\n", + (void *) (unsigned long) p->address); + } + break; + + case ACPI_MADT_IOSAPIC: + { + struct acpi_table_iosapic *p = + (struct acpi_table_iosapic*) header; + printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] global_irq_base[0x%x] address[%p])\n", + p->id, p->global_irq_base, (void *) (unsigned long) p->address); + } + break; + + case ACPI_MADT_LSAPIC: + { + struct acpi_table_lsapic *p = + (struct acpi_table_lsapic*) header; + printk(KERN_INFO PREFIX "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n", + p->acpi_id, p->id, p->eid, p->flags.enabled?"enabled":"disabled"); + } + break; + + case ACPI_MADT_PLAT_INT_SRC: + { + struct acpi_table_plat_int_src *p = + (struct acpi_table_plat_int_src*) header; + printk(KERN_INFO PREFIX "PLAT_INT_SRC (polarity[0x%x] trigger[0x%x] type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n", + p->flags.polarity, p->flags.trigger, p->type, p->id, p->eid, p->iosapic_vector, p->global_irq); + } + break; + + default: + printk(KERN_WARNING PREFIX "Found unsupported MADT entry (type = 0x%x)\n", + header->type); + break; + } +} + + +static int +acpi_table_compute_checksum ( + void *table_pointer, + unsigned long length) +{ + u8 *p = (u8 *) table_pointer; + unsigned long remains = length; + unsigned long sum = 0; + + if (!p || !length) + return -EINVAL; + + while (remains--) + sum += *p++; + + return (sum & 0xFF); +} + + +int __init +acpi_table_parse_madt ( + enum acpi_table_id id, + acpi_madt_entry_handler handler) +{ + struct acpi_table_madt *madt = NULL; + acpi_table_entry_header *entry = NULL; + unsigned long count = 0; + unsigned long madt_end = 0; + int i = 0; + + if (!handler) + return -EINVAL; + + /* Locate the MADT (if exists). There should only be one. */ + + for (i = 0; i < sdt.count; i++) { + if (sdt.entry[i].id != ACPI_APIC) + continue; + madt = (struct acpi_table_madt *) + __acpi_map_table(sdt.entry[i].pa, sdt.entry[i].size); + if (!madt) { + printk(KERN_WARNING PREFIX "Unable to map MADT\n"); + return -ENODEV; + } + break; + } + + if (!madt) { + printk(KERN_WARNING PREFIX "MADT not present\n"); + return -ENODEV; + } + + madt_end = (unsigned long) madt + sdt.entry[i].size; + + /* Parse all entries looking for a match. */ + + entry = (acpi_table_entry_header *) + ((unsigned long) madt + sizeof(struct acpi_table_madt)); + + while (((unsigned long) entry) < madt_end) { + if (entry->type == id) { + count++; + handler(entry); + } + entry = (acpi_table_entry_header *) + ((unsigned long) entry += entry->length); + } + + return count; +} + + +int __init +acpi_table_parse ( + enum acpi_table_id id, + acpi_table_handler handler) +{ + int count = 0; + int i = 0; + + if (!handler) + return -EINVAL; + + for (i = 0; i < sdt.count; i++) { + if (sdt.entry[i].id != id) + continue; + handler(sdt.entry[i].pa, sdt.entry[i].size); + count++; + } + + return count; +} + + +static int __init +acpi_table_get_sdt ( + struct acpi_table_rsdp *rsdp) +{ + struct acpi_table_header *header = NULL; + int i, id = 0; + + if (!rsdp) + return -EINVAL; + + /* First check XSDT (but only on ACPI 2.0-compatible systems) */ + + if ((rsdp->revision >= 2) && + (((struct acpi20_table_rsdp*)rsdp)->xsdt_address)) { + + struct acpi_table_xsdt *mapped_xsdt = NULL; + + sdt.pa = ((struct acpi20_table_rsdp*)rsdp)->xsdt_address; + + header = (struct acpi_table_header *) + __acpi_map_table(sdt.pa, sizeof(struct acpi_table_header)); + + if (!header) { + printk(KERN_WARNING PREFIX "Unable to map XSDT header\n"); + return -ENODEV; + } + + if (strncmp(header->signature, "XSDT", 4)) { + printk(KERN_WARNING PREFIX "XSDT signature incorrect\n"); + return -ENODEV; + } + + sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 3; + if (sdt.count > ACPI_MAX_TABLES) { + printk(KERN_WARNING PREFIX "Truncated %lu XSDT entries\n", + (ACPI_MAX_TABLES - sdt.count)); + sdt.count = ACPI_MAX_TABLES; + } + + mapped_xsdt = (struct acpi_table_xsdt *) + __acpi_map_table(sdt.pa, header->length); + if (!mapped_xsdt) { + printk(KERN_WARNING PREFIX "Unable to map XSDT\n"); + return -ENODEV; + } + + header = &mapped_xsdt->header; + + for (i = 0; i < sdt.count; i++) + sdt.entry[i].pa = (unsigned long) mapped_xsdt->entry[i]; + } + + /* Then check RSDT */ + + else if (rsdp->rsdt_address) { + + struct acpi_table_rsdt *mapped_rsdt = NULL; + + sdt.pa = rsdp->rsdt_address; + + header = (struct acpi_table_header *) + __acpi_map_table(sdt.pa, sizeof(struct acpi_table_header)); + if (!header) { + printk(KERN_WARNING PREFIX "Unable to map RSDT header\n"); + return -ENODEV; + } + + if (strncmp(header->signature, "RSDT", 4)) { + printk(KERN_WARNING PREFIX "RSDT signature incorrect\n"); + return -ENODEV; + } + + sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 2; + if (sdt.count > ACPI_MAX_TABLES) { + printk(KERN_WARNING PREFIX "Truncated %lu RSDT entries\n", + (ACPI_TABLE_COUNT - sdt.count)); + sdt.count = ACPI_MAX_TABLES; + } + + mapped_rsdt = (struct acpi_table_rsdt *) + __acpi_map_table(sdt.pa, header->length); + if (!mapped_rsdt) { + printk(KERN_WARNING PREFIX "Unable to map RSDT\n"); + return -ENODEV; + } + + header = &mapped_rsdt->header; + + for (i = 0; i < sdt.count; i++) + sdt.entry[i].pa = (unsigned long) mapped_rsdt->entry[i]; + } + + else { + printk(KERN_WARNING PREFIX "No System Description Table (RSDT/XSDT) specified in RSDP\n"); + return -ENODEV; + } + + acpi_table_print(header, sdt.pa); + + for (i = 0; i < sdt.count; i++) { + + header = (struct acpi_table_header *) + __acpi_map_table(sdt.entry[i].pa, + sizeof(struct acpi_table_header)); + if (!header) + continue; + + acpi_table_print(header, sdt.entry[i].pa); + + if (acpi_table_compute_checksum(header, header->length)) { + printk(KERN_WARNING " >>> ERROR: Invalid checksum\n"); + continue; + } + + sdt.entry[i].size = header->length; + + for (id = 0; id < ACPI_TABLE_COUNT; id++) { + if (!strncmp((char *) &header->signature, + acpi_table_signatures[id], + sizeof(header->signature))) { + sdt.entry[i].id = id; + } + } + } + + return 0; +} + + +int __init +acpi_table_init ( + char *cmdline) +{ + struct acpi_table_rsdp *rsdp = NULL; + unsigned long rsdp_phys = 0; + int result = 0; + + memset(&sdt, 0, sizeof(struct acpi_table_sdt)); + memset(&madt_handlers, 0, sizeof(madt_handlers)); + + /* Locate and map the Root System Description Table (RSDP) */ + + rsdp_phys = acpi_find_rsdp(); + if (!rsdp_phys) { + printk(KERN_ERR PREFIX "Unable to locate RSDP\n"); + return -ENODEV; + } + + rsdp = (struct acpi_table_rsdp *) __va(rsdp_phys); + if (!rsdp) { + printk(KERN_WARNING PREFIX "Unable to map RSDP\n"); + return -ENODEV; + } + + printk(KERN_INFO PREFIX "RSDP (v%3.3d %6.6s ) @ 0x%p\n", + rsdp->revision, rsdp->oem_id, (void *) rsdp_phys); + + if (rsdp->revision < 2) + result = acpi_table_compute_checksum(rsdp, sizeof(struct acpi_table_rsdp)); + else + result = acpi_table_compute_checksum(rsdp, ((struct acpi20_table_rsdp *)rsdp)->length); + + if (result) { + printk(KERN_WARNING " >>> ERROR: Invalid checksum\n"); + return -ENODEV; + } + + /* Locate and map the System Description table (RSDT/XSDT) */ + + if (acpi_table_get_sdt(rsdp)) + return -ENODEV; + + return 0; +} + diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/thermal.c Sun Jun 2 18:44:57 2002 @@ -0,0 +1,1317 @@ +/* + * acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 39 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This driver fully implements the ACPI thermal policy as described in the + * ACPI 2.0 Specification. + * + * TBD: 1. Implement passive cooling hysteresis. + * 2. Enhance passive cooling (CPU) states/limit interface to support + * concepts of 'multiple limiters', upper/lower limits, etc. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_THERMAL_COMPONENT +ACPI_MODULE_NAME ("acpi_thermal") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +static int tzp = 0; +MODULE_PARM(tzp, "i"); +MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); + +#define PREFIX "ACPI: " + + +#define ACPI_THERMAL_MAX_ACTIVE 10 + +#define KELVIN_TO_CELSIUS(t) ((t-2732+5)/10) + +static int acpi_thermal_add (struct acpi_device *device); +static int acpi_thermal_remove (struct acpi_device *device, int type); + +static struct acpi_driver acpi_thermal_driver = { + name: ACPI_THERMAL_DRIVER_NAME, + class: ACPI_THERMAL_CLASS, + ids: ACPI_THERMAL_HID, + ops: { + add: acpi_thermal_add, + remove: acpi_thermal_remove, + }, +}; + +struct acpi_thermal_state { + u8 critical:1; + u8 hot:1; + u8 passive:1; + u8 active:1; + u8 reserved:4; + int active_index; +}; + +struct acpi_thermal_state_flags { + u8 valid:1; + u8 enabled:1; + u8 reserved:6; +}; + +struct acpi_thermal_critical { + struct acpi_thermal_state_flags flags; + unsigned long temperature; +}; + +struct acpi_thermal_hot { + struct acpi_thermal_state_flags flags; + unsigned long temperature; +}; + +struct acpi_thermal_passive { + struct acpi_thermal_state_flags flags; + unsigned long temperature; + unsigned long tc1; + unsigned long tc2; + unsigned long tsp; + struct acpi_handle_list devices; +}; + +struct acpi_thermal_active { + struct acpi_thermal_state_flags flags; + unsigned long temperature; + struct acpi_handle_list devices; +}; + +struct acpi_thermal_trips { + struct acpi_thermal_critical critical; + struct acpi_thermal_hot hot; + struct acpi_thermal_passive passive; + struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE]; +}; + +struct acpi_thermal_flags { + u8 cooling_mode:1; /* _SCP */ + u8 devices:1; /* _TZD */ + u8 reserved:6; +}; + +struct acpi_thermal { + acpi_handle handle; + acpi_bus_id name; + unsigned long temperature; + unsigned long last_temperature; + unsigned long polling_frequency; + u8 cooling_mode; + struct acpi_thermal_flags flags; + struct acpi_thermal_state state; + struct acpi_thermal_trips trips; + struct acpi_handle_list devices; + struct timer_list timer; +}; + + +/* -------------------------------------------------------------------------- + Thermal Zone Management + -------------------------------------------------------------------------- */ + +static int +acpi_thermal_get_temperature ( + struct acpi_thermal *tz) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_thermal_get_temperature"); + + if (!tz) + return_VALUE(-EINVAL); + + tz->last_temperature = tz->temperature; + + status = acpi_evaluate_integer(tz->handle, "_TMP", NULL, &tz->temperature); + if (ACPI_FAILURE(status)) + return -ENODEV; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n", tz->temperature)); + + return_VALUE(0); +} + + +static int +acpi_thermal_get_polling_frequency ( + struct acpi_thermal *tz) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_thermal_get_polling_frequency"); + + if (!tz) + return_VALUE(-EINVAL); + + status = acpi_evaluate_integer(tz->handle, "_TZP", NULL, &tz->polling_frequency); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n", tz->polling_frequency)); + + return_VALUE(0); +} + + +static int +acpi_thermal_set_polling ( + struct acpi_thermal *tz, + int seconds) +{ + ACPI_FUNCTION_TRACE("acpi_thermal_set_polling"); + + if (!tz) + return_VALUE(-EINVAL); + + tz->polling_frequency = seconds * 10; /* Convert value to deci-seconds */ + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency set to %lu seconds\n", tz->polling_frequency)); + + return_VALUE(0); +} + + +static int +acpi_thermal_set_cooling_mode ( + struct acpi_thermal *tz, + int mode) +{ + acpi_status status = AE_OK; + acpi_object arg0 = {ACPI_TYPE_INTEGER}; + acpi_object_list arg_list= {1, &arg0}; + acpi_handle handle = NULL; + + ACPI_FUNCTION_TRACE("acpi_thermal_set_cooling_mode"); + + if (!tz) + return_VALUE(-EINVAL); + + status = acpi_get_handle(tz->handle, "_SCP", &handle); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n")); + return_VALUE(-ENODEV); + } + + arg0.integer.value = mode; + + status = acpi_evaluate(handle, NULL, &arg_list, NULL); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + tz->cooling_mode = mode; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n", + mode?"passive":"active")); + + return_VALUE(0); +} + + +static int +acpi_thermal_get_trip_points ( + struct acpi_thermal *tz) +{ + acpi_status status = AE_OK; + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_thermal_get_trip_points"); + + if (!tz) + return_VALUE(-EINVAL); + + /* Critical Shutdown (required) */ + + status = acpi_evaluate_integer(tz->handle, "_CRT", NULL, + &tz->trips.critical.temperature); + if (ACPI_FAILURE(status)) { + tz->trips.critical.flags.valid = 0; + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No critical threshold\n")); + return -ENODEV; + } + else { + tz->trips.critical.flags.valid = 1; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found critical threshold [%lu]\n", tz->trips.critical.temperature)); + } + + /* Critical Sleep (optional) */ + + status = acpi_evaluate_integer(tz->handle, "_HOT", NULL, &tz->trips.hot.temperature); + if (ACPI_FAILURE(status)) { + tz->trips.hot.flags.valid = 0; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n")); + } + else { + tz->trips.hot.flags.valid = 1; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n", tz->trips.hot.temperature)); + } + + /* Passive: Processors (optional) */ + + status = acpi_evaluate_integer(tz->handle, "_PSV", NULL, &tz->trips.passive.temperature); + if (ACPI_FAILURE(status)) { + tz->trips.passive.flags.valid = 0; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n")); + } + else { + tz->trips.passive.flags.valid = 1; + + status = acpi_evaluate_integer(tz->handle, "_TC1", NULL, &tz->trips.passive.tc1); + if (ACPI_FAILURE(status)) + tz->trips.passive.flags.valid = 0; + + status = acpi_evaluate_integer(tz->handle, "_TC2", NULL, &tz->trips.passive.tc2); + if (ACPI_FAILURE(status)) + tz->trips.passive.flags.valid = 0; + + status = acpi_evaluate_integer(tz->handle, "_TSP", NULL, &tz->trips.passive.tsp); + if (ACPI_FAILURE(status)) + tz->trips.passive.flags.valid = 0; + + status = acpi_evaluate_reference(tz->handle, "_PSL", NULL, &tz->trips.passive.devices); + if (ACPI_FAILURE(status)) + tz->trips.passive.flags.valid = 0; + + if (!tz->trips.passive.flags.valid) + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid passive threshold\n")); + else + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found passive threshold [%lu]\n", tz->trips.passive.temperature)); + } + + /* Active: Fans, etc. (optional) */ + + for (i=0; ihandle, name, NULL, &tz->trips.active[i].temperature); + if (ACPI_FAILURE(status)) + break; + + name[2] = 'L'; + status = acpi_evaluate_reference(tz->handle, name, NULL, &tz->trips.active[i].devices); + if (ACPI_SUCCESS(status)) { + tz->trips.active[i].flags.valid = 1; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found active threshold [%d]:[%lu]\n", i, tz->trips.active[i].temperature)); + } + else + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid active threshold [%d]\n", i)); + } + + return_VALUE(0); +} + + +static int +acpi_thermal_get_devices ( + struct acpi_thermal *tz) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_thermal_get_devices"); + + if (!tz) + return_VALUE(-EINVAL); + + status = acpi_evaluate_reference(tz->handle, "_TZD", NULL, &tz->devices); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + + +static int +acpi_thermal_call_usermode ( + char *path) +{ + char *argv[2] = {NULL, NULL}; + char *envp[3] = {NULL, NULL, NULL}; + + ACPI_FUNCTION_TRACE("acpi_thermal_call_usermode"); + + if (!path) + return_VALUE(-EINVAL);; + + argv[0] = path; + + /* minimal command environment */ + envp[0] = "HOME=/"; + envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; + + call_usermodehelper(argv[0], argv, envp); + + return_VALUE(0); +} + + +static int +acpi_thermal_critical ( + struct acpi_thermal *tz) +{ + int result = 0; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_thermal_critical"); + + if (!tz || !tz->trips.critical.flags.valid) + return_VALUE(-EINVAL); + + if (tz->temperature >= tz->trips.critical.temperature) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Critical trip point\n")); + tz->trips.critical.flags.enabled = 1; + } + else if (tz->trips.critical.flags.enabled) + tz->trips.critical.flags.enabled = 0; + + result = acpi_bus_get_device(tz->handle, &device); + if (result) + return_VALUE(result); + + acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled); + + acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF); + + return_VALUE(0); +} + + +static int +acpi_thermal_hot ( + struct acpi_thermal *tz) +{ + int result = 0; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_thermal_hot"); + + if (!tz || !tz->trips.hot.flags.valid) + return_VALUE(-EINVAL); + + if (tz->temperature >= tz->trips.hot.temperature) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Hot trip point\n")); + tz->trips.hot.flags.enabled = 1; + } + else if (tz->trips.hot.flags.enabled) + tz->trips.hot.flags.enabled = 0; + + result = acpi_bus_get_device(tz->handle, &device); + if (result) + return_VALUE(result); + + acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled); + + /* TBD: Call user-mode "sleep(S4)" function */ + + return_VALUE(0); +} + + +static int +acpi_thermal_passive ( + struct acpi_thermal *tz) +{ + int result = 0; + struct acpi_thermal_passive *passive = NULL; + int trend = 0; + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_thermal_passive"); + + if (!tz || !tz->trips.passive.flags.valid) + return_VALUE(-EINVAL); + + passive = &(tz->trips.passive); + + /* + * Above Trip? + * ----------- + * Calculate the thermal trend (using the passive cooling equation) + * and modify the performance limit for all passive cooling devices + * accordingly. Note that we assume symmetry. + */ + if (tz->temperature >= passive->temperature) { + trend = (passive->tc1 * (tz->temperature - tz->last_temperature)) + (passive->tc2 * (tz->temperature - passive->temperature)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n", + trend, passive->tc1, tz->temperature, + tz->last_temperature, passive->tc2, + tz->temperature, passive->temperature)); + /* Heating up? */ + if (trend > 0) + for (i=0; idevices.count; i++) + acpi_processor_set_thermal_limit( + passive->devices.handles[i], + ACPI_PROCESSOR_LIMIT_INCREMENT); + /* Cooling off? */ + else if (trend < 0) + for (i=0; idevices.count; i++) + acpi_processor_set_thermal_limit( + passive->devices.handles[i], + ACPI_PROCESSOR_LIMIT_DECREMENT); + } + + /* + * Below Trip? + * ----------- + * Implement passive cooling hysteresis to slowly increase performance + * and avoid thrashing around the passive trip point. Note that we + * assume symmetry. + */ + else if (tz->trips.passive.flags.enabled) { + for (i=0; idevices.count; i++) + result = acpi_processor_set_thermal_limit( + passive->devices.handles[i], + ACPI_PROCESSOR_LIMIT_DECREMENT); + if (result == 1) { + tz->trips.passive.flags.enabled = 0; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Disabling passive cooling (zone is cool)\n")); + } + } + + return_VALUE(0); +} + + +static int +acpi_thermal_active ( + struct acpi_thermal *tz) +{ + int result = 0; + struct acpi_thermal_active *active = NULL; + int i = 0; + int j = 0; + + ACPI_FUNCTION_TRACE("acpi_thermal_active"); + + if (!tz) + return_VALUE(-EINVAL); + + for (i=0; itrips.active[i]); + if (!active || !active->flags.valid) + break; + + /* + * Above Threshold? + * ---------------- + * If not already enabled, turn ON all cooling devices + * associated with this active threshold. + */ + if (tz->temperature >= active->temperature) { + tz->state.active_index = i; + if (!active->flags.enabled) { + for (j = 0; j < active->devices.count; j++) { + result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D0); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'on'\n", active->devices.handles[j])); + continue; + } + active->flags.enabled = 1; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'on'\n", active->devices.handles[j])); + } + } + } + /* + * Below Threshold? + * ---------------- + * Turn OFF all cooling devices associated with this + * threshold. + */ + else if (active->flags.enabled) { + for (j = 0; j < active->devices.count; j++) { + result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D3); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'off'\n", active->devices.handles[j])); + continue; + } + active->flags.enabled = 0; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'off'\n", active->devices.handles[j])); + } + } + } + + return_VALUE(0); +} + + +static void acpi_thermal_check (void *context); + +static void +acpi_thermal_run ( + unsigned long data) +{ + acpi_os_queue_for_execution(OSD_PRIORITY_GPE, acpi_thermal_check, (void *) data); +} + + +static void +acpi_thermal_check ( + void *data) +{ + int result = 0; + struct acpi_thermal *tz = (struct acpi_thermal *) data; + unsigned long sleep_time = 0; + int i = 0; + + ACPI_FUNCTION_TRACE("acpi_thermal_check"); + + if (!tz) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) context.\n")); + return_VOID; + } + + result = acpi_thermal_get_temperature(tz); + if (result) + return_VOID; + + memset(&tz->state, 0, sizeof(tz->state)); + + /* + * Check Trip Points + * ----------------- + * Compare the current temperature to the trip point values to see + * if we've entered one of the thermal policy states. Note that + * this function determines when a state is entered, but the + * individual policy decides when it is exited (e.g. hysteresis). + */ + if ((tz->trips.critical.flags.valid) && (tz->temperature >= tz->trips.critical.temperature)) + tz->trips.critical.flags.enabled = 1; + if ((tz->trips.hot.flags.valid) && (tz->temperature >= tz->trips.hot.temperature)) + tz->trips.hot.flags.enabled = 1; + if ((tz->trips.passive.flags.valid) && (tz->temperature >= tz->trips.passive.temperature)) + tz->trips.passive.flags.enabled = 1; + for (i=0; itrips.active[i].flags.valid) && (tz->temperature >= tz->trips.active[i].temperature)) + tz->trips.active[i].flags.enabled = 1; + + /* + * Invoke Policy + * ------------- + * Separated from the above check to allow individual policy to + * determine when to exit a given state. + */ + if (tz->trips.critical.flags.enabled) + acpi_thermal_critical(tz); + if (tz->trips.hot.flags.enabled) + acpi_thermal_hot(tz); + if (tz->trips.passive.flags.enabled) + acpi_thermal_passive(tz); + if (tz->trips.active[0].flags.enabled) + acpi_thermal_active(tz); + + /* + * Calculate State + * --------------- + * Again, separated from the above two to allow independent policy + * decisions. + */ + if (tz->trips.critical.flags.enabled) + tz->state.critical = 1; + if (tz->trips.hot.flags.enabled) + tz->state.hot = 1; + if (tz->trips.passive.flags.enabled) + tz->state.passive = 1; + for (i=0; itrips.active[i].flags.enabled) + tz->state.active = 1; + + /* + * Calculate Sleep Time + * -------------------- + * If we're in the passive state, use _TSP's value. Otherwise + * use the default polling frequency (e.g. _TZP). If no polling + * frequency is specified then we'll wait forever (at least until + * a thermal event occurs). Note that _TSP and _TZD values are + * given in 1/10th seconds (we must covert to milliseconds). + */ + if (tz->state.passive) + sleep_time = tz->trips.passive.tsp * 100; + else if (tz->polling_frequency > 0) + sleep_time = tz->polling_frequency * 100; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n", + tz->name, tz->temperature, sleep_time)); + + /* + * Schedule Next Poll + * ------------------ + */ + if (!sleep_time) { + if (timer_pending(&(tz->timer))) + del_timer(&(tz->timer)); + } + else { + if (timer_pending(&(tz->timer))) + mod_timer(&(tz->timer), (HZ * sleep_time) / 1000); + else { + tz->timer.data = (unsigned long) tz; + tz->timer.function = acpi_thermal_run; + tz->timer.expires = jiffies + (HZ * sleep_time) / 1000; + add_timer(&(tz->timer)); + } + } + + return_VOID; +} + + +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +struct proc_dir_entry *acpi_thermal_dir = NULL; + + +static int +acpi_thermal_read_state ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_thermal *tz = (struct acpi_thermal *) data; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_thermal_read_state"); + + if (!tz || (off != 0)) + goto end; + + p += sprintf(p, "state: "); + + if (!tz->state.critical && !tz->state.hot && !tz->state.passive && !tz->state.active) + p += sprintf(p, "ok\n"); + else { + if (tz->state.critical) + p += sprintf(p, "critical "); + if (tz->state.hot) + p += sprintf(p, "hot "); + if (tz->state.passive) + p += sprintf(p, "passive "); + if (tz->state.active) + p += sprintf(p, "active[%d]", tz->state.active_index); + p += sprintf(p, "\n"); + } + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_thermal_read_temperature ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + int result = 0; + struct acpi_thermal *tz = (struct acpi_thermal *) data; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_thermal_read_temperature"); + + if (!tz || (off != 0)) + goto end; + + result = acpi_thermal_get_temperature(tz); + if (result) + goto end; + + p += sprintf(p, "temperature: %lu C\n", + KELVIN_TO_CELSIUS(tz->temperature)); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_thermal_read_trip_points ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_thermal *tz = (struct acpi_thermal *) data; + char *p = page; + int len = 0; + int i = 0; + int j = 0; + + ACPI_FUNCTION_TRACE("acpi_thermal_read_trip_points"); + + if (!tz || (off != 0)) + goto end; + + if (tz->trips.critical.flags.valid) + p += sprintf(p, "critical (S5): %lu C\n", + KELVIN_TO_CELSIUS(tz->trips.critical.temperature)); + + if (tz->trips.hot.flags.valid) + p += sprintf(p, "hot (S4): %lu C\n", + KELVIN_TO_CELSIUS(tz->trips.hot.temperature)); + + if (tz->trips.passive.flags.valid) { + p += sprintf(p, "passive: %lu C: tc1=%lu tc2=%lu tsp=%lu devices=", + KELVIN_TO_CELSIUS(tz->trips.passive.temperature), + tz->trips.passive.tc1, + tz->trips.passive.tc2, + tz->trips.passive.tsp); + for (j=0; jtrips.passive.devices.count; j++) { + + p += sprintf(p, "0x%p ", tz->trips.passive.devices.handles[j]); + } + p += sprintf(p, "\n"); + } + + for (i=0; itrips.active[i].flags.valid)) + break; + p += sprintf(p, "active[%d]: %lu C: devices=", + i, KELVIN_TO_CELSIUS(tz->trips.active[i].temperature)); + for (j=0; jtrips.active[i].devices.count; j++) + p += sprintf(p, "0x%p ", + tz->trips.active[i].devices.handles[j]); + p += sprintf(p, "\n"); + } + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_thermal_read_cooling_mode ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_thermal *tz = (struct acpi_thermal *) data; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_thermal_read_cooling_mode"); + + if (!tz || (off != 0)) + goto end; + + if (!tz->flags.cooling_mode) { + p += sprintf(p, "\n"); + goto end; + } + + p += sprintf(p, "cooling mode: %s\n", + tz->cooling_mode?"passive":"active"); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_thermal_write_cooling_mode ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + struct acpi_thermal *tz = (struct acpi_thermal *) data; + char mode_string[12] = {'\0'}; + + ACPI_FUNCTION_TRACE("acpi_thermal_write_cooling_mode"); + + if (!tz || (count > sizeof(mode_string) - 1)) + return_VALUE(-EINVAL); + + if (!tz->flags.cooling_mode) + return_VALUE(-ENODEV); + + if (copy_from_user(mode_string, buffer, count)) + return_VALUE(-EFAULT); + + mode_string[count] = '\0'; + + result = acpi_thermal_set_cooling_mode(tz, + simple_strtoul(mode_string, NULL, 0)); + if (result) + return_VALUE(result); + + return_VALUE(count); +} + + +static int +acpi_thermal_read_polling ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + struct acpi_thermal *tz = (struct acpi_thermal *) data; + char *p = page; + int len = 0; + + ACPI_FUNCTION_TRACE("acpi_thermal_read_polling"); + + if (!tz || (off != 0)) + goto end; + + if (!tz->polling_frequency) { + p += sprintf(p, "\n"); + goto end; + } + + p += sprintf(p, "polling frequency: %lu seconds\n", + (tz->polling_frequency / 10)); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + + return_VALUE(len); +} + + +static int +acpi_thermal_write_polling ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + struct acpi_thermal *tz = (struct acpi_thermal *) data; + char polling_string[12] = {'\0'}; + int seconds = 0; + + ACPI_FUNCTION_TRACE("acpi_thermal_write_polling"); + + if (!tz || (count > sizeof(polling_string) - 1)) + return_VALUE(-EINVAL); + + if (copy_from_user(polling_string, buffer, count)) + return_VALUE(-EFAULT); + + polling_string[count] = '\0'; + + seconds = simple_strtoul(polling_string, NULL, 0); + + result = acpi_thermal_set_polling(tz, seconds); + if (result) + return_VALUE(result); + + acpi_thermal_check(tz); + + return_VALUE(count); +} + + +static int +acpi_thermal_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + + ACPI_FUNCTION_TRACE("acpi_thermal_add_fs"); + + if (!acpi_thermal_dir) { + acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, + acpi_root_dir); + if (!acpi_thermal_dir) + return_VALUE(-ENODEV); + } + + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_thermal_dir); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + } + + /* 'state' [R] */ + entry = create_proc_entry(ACPI_THERMAL_FILE_STATE, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_THERMAL_FILE_STATE)); + else { + entry->read_proc = acpi_thermal_read_state; + entry->data = acpi_driver_data(device); + } + + /* 'temperature' [R] */ + entry = create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_THERMAL_FILE_TEMPERATURE)); + else { + entry->read_proc = acpi_thermal_read_temperature; + entry->data = acpi_driver_data(device); + } + + /* 'trip_points' [R] */ + entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_THERMAL_FILE_POLLING_FREQ)); + else { + entry->read_proc = acpi_thermal_read_trip_points; + entry->data = acpi_driver_data(device); + } + + /* 'cooling_mode' [R/W] */ + entry = create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_THERMAL_FILE_COOLING_MODE)); + else { + entry->read_proc = acpi_thermal_read_cooling_mode; + entry->write_proc = acpi_thermal_write_cooling_mode; + entry->data = acpi_driver_data(device); + } + + /* 'polling_frequency' [R/W] */ + entry = create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ, + S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_THERMAL_FILE_POLLING_FREQ)); + else { + entry->read_proc = acpi_thermal_read_polling; + entry->write_proc = acpi_thermal_write_polling; + entry->data = acpi_driver_data(device); + } + + return_VALUE(0); +} + + +static int +acpi_thermal_remove_fs ( + struct acpi_device *device) +{ + ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs"); + + if (!acpi_thermal_dir) + return_VALUE(-ENODEV); + + if (acpi_device_dir(device)) + remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir); + + return_VALUE(0); +} + + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +static void +acpi_thermal_notify ( + acpi_handle handle, + u32 event, + void *data) +{ + struct acpi_thermal *tz = (struct acpi_thermal *) data; + struct acpi_device *device = NULL; + + ACPI_FUNCTION_TRACE("acpi_thermal_notify"); + + if (!tz) + return_VOID; + + if (acpi_bus_get_device(tz->handle, &device)) + return_VOID; + + switch (event) { + case ACPI_THERMAL_NOTIFY_TEMPERATURE: + acpi_thermal_check(tz); + break; + case ACPI_THERMAL_NOTIFY_THRESHOLDS: + acpi_thermal_get_trip_points(tz); + acpi_thermal_check(tz); + acpi_bus_generate_event(device, event, 0); + break; + case ACPI_THERMAL_NOTIFY_DEVICES: + if (tz->flags.devices) + acpi_thermal_get_devices(tz); + acpi_bus_generate_event(device, event, 0); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Unsupported event [0x%x]\n", event)); + break; + } + + return_VOID; +} + + +static int +acpi_thermal_get_info ( + struct acpi_thermal *tz) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_thermal_get_info"); + + if (!tz) + return_VALUE(-EINVAL); + + /* Get temperature [_TMP] (required) */ + result = acpi_thermal_get_temperature(tz); + if (result) + return_VALUE(result); + + /* Set the cooling mode [_SCP] to active cooling (default) */ + result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE); + if (!result) + tz->flags.cooling_mode = 1; + + /* Get trip points [_CRT, _PSV, etc.] (required) */ + result = acpi_thermal_get_trip_points(tz); + if (result) + return_VALUE(result); + + /* Get default polling frequency [_TZP] (optional) */ + if (tzp) + tz->polling_frequency = tzp; + else + acpi_thermal_get_polling_frequency(tz); + + /* Get devices in this thermal zone [_TZD] (optional) */ + result = acpi_thermal_get_devices(tz); + if (!result) + tz->flags.devices = 1; + + return_VALUE(0); +} + + +static int +acpi_thermal_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_thermal *tz = NULL; + + ACPI_FUNCTION_TRACE("acpi_thermal_add"); + + if (!device) + return_VALUE(-EINVAL); + + tz = kmalloc(sizeof(struct acpi_thermal), GFP_KERNEL); + if (!tz) + return_VALUE(-ENOMEM); + memset(tz, 0, sizeof(struct acpi_thermal)); + + tz->handle = device->handle; + sprintf(tz->name, "%s", device->pnp.bus_id); + sprintf(acpi_device_name(device), "%s", ACPI_THERMAL_DEVICE_NAME); + sprintf(acpi_device_class(device), "%s", ACPI_THERMAL_CLASS); + acpi_driver_data(device) = tz; + + result = acpi_thermal_get_info(tz); + if (result) + goto end; + + result = acpi_thermal_add_fs(device); + if (result) + return_VALUE(result); + + acpi_thermal_check(tz); + + status = acpi_install_notify_handler(tz->handle, + ACPI_DEVICE_NOTIFY, acpi_thermal_notify, tz); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error installing notify handler\n")); + result = -ENODEV; + goto end; + } + + init_timer(&tz->timer); + + printk(KERN_INFO PREFIX "%s [%s] (%lu C)\n", + acpi_device_name(device), acpi_device_bid(device), + KELVIN_TO_CELSIUS(tz->temperature)); + +end: + if (result) { + acpi_thermal_remove_fs(device); + kfree(tz); + } + + return_VALUE(result); +} + + +static int +acpi_thermal_remove ( + struct acpi_device *device, + int type) +{ + acpi_status status = AE_OK; + struct acpi_thermal *tz = NULL; + + ACPI_FUNCTION_TRACE("acpi_thermal_remove"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + tz = (struct acpi_thermal *) acpi_driver_data(device); + + if (timer_pending(&(tz->timer))) + del_timer(&(tz->timer)); + + status = acpi_remove_notify_handler(tz->handle, + ACPI_DEVICE_NOTIFY, acpi_thermal_notify); + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error removing notify handler\n")); + + /* Terminate policy */ + if (tz->trips.passive.flags.valid + && tz->trips.passive.flags.enabled) { + tz->trips.passive.flags.enabled = 0; + acpi_thermal_passive(tz); + } + if (tz->trips.active[0].flags.valid + && tz->trips.active[0].flags.enabled) { + tz->trips.active[0].flags.enabled = 0; + acpi_thermal_active(tz); + } + + acpi_thermal_remove_fs(device); + + return_VALUE(0); +} + + +static int __init +acpi_thermal_init (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_thermal_init"); + + result = acpi_bus_register_driver(&acpi_thermal_driver); + if (result < 0) + return_VALUE(-ENODEV); + + return_VALUE(0); +} + + +static void __exit +acpi_thermal_exit (void) +{ + int result = 0; + + ACPI_FUNCTION_TRACE("acpi_thermal_exit"); + + result = acpi_bus_unregister_driver(&acpi_thermal_driver); + if (!result) + remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); + + return_VOID; +} + + +module_init(acpi_thermal_init); +module_exit(acpi_thermal_exit); diff -Nru a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c --- a/drivers/acpi/utilities/utalloc.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/utilities/utalloc.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: utalloc - local cache and memory allocation routines - * $Revision: 121 $ + * $Revision: 127 $ * *****************************************************************************/ @@ -25,10 +25,6 @@ #include "acpi.h" -#include "acparser.h" -#include "acinterp.h" -#include "acnamesp.h" -#include "acglobal.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME ("utalloc") @@ -77,11 +73,11 @@ /* Mark the object as cached */ ACPI_MEMSET (object, 0xCA, cache_info->object_size); - ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_CACHED_OBJECT); + ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_CACHED); /* Put the object at the head of the cache list */ - * (char **) (((char *) object) + cache_info->link_offset) = cache_info->list_head; + * (ACPI_CAST_INDIRECT_PTR (char, &(((char *) object)[cache_info->link_offset]))) = cache_info->list_head; cache_info->list_head = object; cache_info->cache_depth++; @@ -128,7 +124,7 @@ /* There is an object available, use it */ object = cache_info->list_head; - cache_info->list_head = * (char **) (((char *) object) + cache_info->link_offset); + cache_info->list_head = *(ACPI_CAST_INDIRECT_PTR (char, &(((char *) object)[cache_info->link_offset]))); ACPI_MEM_TRACKING (cache_info->cache_hits++); cache_info->cache_depth--; @@ -191,7 +187,7 @@ while (cache_info->list_head) { /* Delete one cached state object */ - next = * (char **) (((char *) cache_info->list_head) + cache_info->link_offset); + next = *(ACPI_CAST_INDIRECT_PTR (char, &(((char *) cache_info->list_head)[cache_info->link_offset]))); ACPI_MEM_FREE (cache_info->list_head); cache_info->list_head = next; @@ -362,7 +358,7 @@ /* Report allocation error */ _ACPI_REPORT_ERROR (module, line, component, - ("Ut_allocate: Could not allocate size %X\n", size)); + ("Ut_allocate: Could not allocate size %X\n", (u32) size)); return_PTR (NULL); } @@ -412,7 +408,7 @@ /* Report allocation error */ _ACPI_REPORT_ERROR (module, line, component, - ("Ut_callocate: Could not allocate size %X\n", size)); + ("Ut_callocate: Could not allocate size %X\n", (u32) size)); return_PTR (NULL); } @@ -514,7 +510,7 @@ /* Report allocation error */ _ACPI_REPORT_ERROR (module, line, component, - ("Ut_callocate: Could not allocate size %X\n", size)); + ("Ut_callocate: Could not allocate size %X\n", (u32) size)); return (NULL); } @@ -555,6 +551,7 @@ u32 line) { acpi_debug_mem_block *debug_block; + acpi_status status; ACPI_FUNCTION_TRACE_PTR ("Ut_free", allocation); @@ -567,14 +564,19 @@ return_VOID; } - debug_block = (acpi_debug_mem_block *) - (((char *) allocation) - sizeof (acpi_debug_mem_header)); + debug_block = ACPI_CAST_PTR (acpi_debug_mem_block, + (((char *) allocation) - sizeof (acpi_debug_mem_header))); acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].total_freed++; acpi_gbl_memory_lists[ACPI_MEM_LIST_GLOBAL].current_total_size -= debug_block->size; - acpi_ut_remove_allocation (ACPI_MEM_LIST_GLOBAL, debug_block, - component, module, line); + status = acpi_ut_remove_allocation (ACPI_MEM_LIST_GLOBAL, debug_block, + component, module, line); + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not free memory, %s\n", + acpi_format_exception (status))); + } + acpi_os_free (debug_block); ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation)); @@ -864,6 +866,7 @@ NATIVE_CHAR *module) { acpi_debug_mem_block *element; + ACPI_DESCRIPTOR *descriptor; u32 num_outstanding = 0; @@ -883,28 +886,29 @@ ((module == NULL) || (0 == ACPI_STRCMP (module, element->module)))) { /* Ignore allocated objects that are in a cache */ - if (((acpi_operand_object *)(&element->user_space))->common.type != ACPI_CACHED_OBJECT) { + descriptor = ACPI_CAST_PTR (ACPI_DESCRIPTOR, &element->user_space); + if (descriptor->descriptor_id != ACPI_DESC_TYPE_CACHED) { acpi_os_printf ("%p Len %04X %9.9s-%d ", - &element->user_space, element->size, element->module, + descriptor, element->size, element->module, element->line); /* Most of the elements will be internal objects. */ - switch (ACPI_GET_DESCRIPTOR_TYPE (&element->user_space)) { - case ACPI_DESC_TYPE_INTERNAL: - acpi_os_printf ("Obj_type %12.12s R%d", - acpi_ut_get_type_name (((acpi_operand_object *)(&element->user_space))->common.type), - ((acpi_operand_object *)(&element->user_space))->common.reference_count); + switch (ACPI_GET_DESCRIPTOR_TYPE (descriptor)) { + case ACPI_DESC_TYPE_OPERAND: + acpi_os_printf ("Obj_type %12.12s R%hd", + acpi_ut_get_type_name (descriptor->object.common.type), + descriptor->object.common.reference_count); break; case ACPI_DESC_TYPE_PARSER: - acpi_os_printf ("Parse_obj Opcode %04X", - ((acpi_parse_object *)(&element->user_space))->opcode); + acpi_os_printf ("Parse_obj Aml_opcode %04hX", + descriptor->op.asl.aml_opcode); break; case ACPI_DESC_TYPE_NAMED: acpi_os_printf ("Node %4.4s", - (char *) &((acpi_namespace_node *)(&element->user_space))->name); + descriptor->node.name.ascii); break; case ACPI_DESC_TYPE_STATE: @@ -946,6 +950,10 @@ case ACPI_DESC_TYPE_STATE_THREAD: acpi_os_printf ("THREAD State_obj"); break; + + default: + /* All types should appear above */ + break; } acpi_os_printf ( "\n"); @@ -961,7 +969,7 @@ if (!num_outstanding) { ACPI_DEBUG_PRINT ((ACPI_DB_OK, - "No outstanding allocations.\n")); + "No outstanding allocations.\n")); } else { ACPI_DEBUG_PRINT ((ACPI_DB_OK, diff -Nru a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c --- a/drivers/acpi/utilities/utcopy.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/utilities/utcopy.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: utcopy - Internal to external object translation utilities - * $Revision: 95 $ + * $Revision: 98 $ * *****************************************************************************/ @@ -25,7 +25,6 @@ #include "acpi.h" -#include "acinterp.h" #include "acnamesp.h" #include "amlcode.h" @@ -92,10 +91,10 @@ external_object->string.pointer = (NATIVE_CHAR *) data_space; external_object->string.length = internal_object->string.length; - *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD (internal_object->string.length + 1); + *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD ((ACPI_SIZE) internal_object->string.length + 1); ACPI_MEMCPY ((void *) data_space, (void *) internal_object->string.pointer, - internal_object->string.length + 1); + (ACPI_SIZE) internal_object->string.length + 1); break; @@ -153,12 +152,12 @@ buffer.length = MAX_STRING_LENGTH; buffer.pointer = data_space; - status = acpi_ns_handle_to_pathname ((acpi_handle *) internal_object->reference.node, + status = acpi_ns_handle_to_pathname ((acpi_handle) internal_object->reference.node, &buffer); /* Converted (external) string length is returned from above */ - external_object->string.length = buffer.length; + external_object->string.length = (u32) buffer.length; *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD (buffer.length); break; @@ -257,7 +256,7 @@ */ target_object->type = ACPI_TYPE_PACKAGE; target_object->package.count = source_object->package.count; - target_object->package.elements = (acpi_object *) info->free_space; + target_object->package.elements = ACPI_CAST_PTR (acpi_object, info->free_space); /* * Pass the new package object back to the package walk routine @@ -269,7 +268,7 @@ * update the buffer length counter */ object_space = ACPI_ROUND_UP_TO_NATIVE_WORD ( - target_object->package.count * sizeof (acpi_object)); + (ACPI_SIZE) target_object->package.count * sizeof (acpi_object)); break; @@ -319,7 +318,7 @@ /* * First package at head of the buffer */ - external_object = (acpi_object *) buffer; + external_object = ACPI_CAST_PTR (acpi_object, buffer); /* * Free space begins right after the first package @@ -331,7 +330,7 @@ external_object->type = internal_object->common.type; external_object->package.count = internal_object->package.count; - external_object->package.elements = (acpi_object *) info.free_space; + external_object->package.elements = ACPI_CAST_PTR (acpi_object, info.free_space); /* * Build an array of ACPI_OBJECTS in the buffer @@ -456,7 +455,7 @@ case ACPI_TYPE_STRING: - internal_object->string.pointer = ACPI_MEM_CALLOCATE (external_object->string.length + 1); + internal_object->string.pointer = ACPI_MEM_CALLOCATE ((ACPI_SIZE) external_object->string.length + 1); if (!internal_object->string.pointer) { return_ACPI_STATUS (AE_NO_MEMORY); } @@ -488,6 +487,10 @@ internal_object->integer.value = external_object->integer.value; break; + + default: + /* Other types can't get here */ + break; } *ret_internal_object = internal_object; @@ -657,6 +660,7 @@ dest_desc->common.flags = source_desc->common.flags; /* Fall through to common string/buffer case */ + /*lint -fallthrough */ case ACPI_TYPE_STRING: @@ -677,6 +681,10 @@ source_desc->string.length); } break; + + default: + /* Nothing to do for other simple objects */ + break; } return (AE_OK); @@ -803,7 +811,7 @@ /* * Create the object array and walk the source package tree */ - dest_obj->package.elements = ACPI_MEM_CALLOCATE ((source_obj->package.count + 1) * + dest_obj->package.elements = ACPI_MEM_CALLOCATE (((ACPI_SIZE) source_obj->package.count + 1) * sizeof (void *)); if (!dest_obj->package.elements) { ACPI_REPORT_ERROR ( diff -Nru a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c --- a/drivers/acpi/utilities/utdebug.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/utilities/utdebug.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: utdebug - Debug print routines - * $Revision: 97 $ + * $Revision: 103 $ * *****************************************************************************/ @@ -30,13 +30,12 @@ ACPI_MODULE_NAME ("utdebug") -u32 acpi_gbl_prev_thread_id = 0xFFFFFFFF; -char *acpi_gbl_fn_entry_str = "----Entry"; -char *acpi_gbl_fn_exit_str = "----Exit-"; - - #ifdef ACPI_DEBUG +static u32 acpi_gbl_prev_thread_id = 0xFFFFFFFF; +static char *acpi_gbl_fn_entry_str = "----Entry"; +static char *acpi_gbl_fn_exit_str = "----Exit-"; + /***************************************************************************** * @@ -132,7 +131,6 @@ return; } - /* * Thread tracking and context switch notification */ @@ -151,14 +149,13 @@ * Display the module name, current line number, thread ID (if requested), * current procedure nesting level, and the current procedure name */ - acpi_os_printf ("%8s-%04d ", dbg_info->module_name, line_number); + acpi_os_printf ("%8s-%04ld ", dbg_info->module_name, line_number); if (ACPI_LV_THREADS & acpi_dbg_level) { - acpi_os_printf ("[%04X] ", thread_id, acpi_gbl_nesting_level, dbg_info->proc_name); + acpi_os_printf ("[%04lX] ", thread_id, acpi_gbl_nesting_level, dbg_info->proc_name); } - acpi_os_printf ("[%02d] %-22.22s: ", acpi_gbl_nesting_level, dbg_info->proc_name); - + acpi_os_printf ("[%02ld] %-22.22s: ", acpi_gbl_nesting_level, dbg_info->proc_name); va_start (args, format); acpi_os_vprintf (format, args); @@ -202,7 +199,6 @@ } va_start (args, format); - acpi_os_vprintf (format, args); } @@ -495,8 +491,8 @@ u32 display, u32 component_id) { - u32 i = 0; - u32 j; + NATIVE_UINT i = 0; + NATIVE_UINT j; u32 temp32; u8 buf_char; @@ -512,7 +508,7 @@ display = DB_BYTE_DISPLAY; } - acpi_os_printf ("\n_offset Value\n"); + acpi_os_printf ("\nOffset Value\n"); /* * Nasty little dump buffer routine! @@ -522,7 +518,6 @@ acpi_os_printf ("%05X ", i); - /* Print 16 hex chars */ for (j = 0; j < 16;) { @@ -576,12 +571,10 @@ } } - /* * Print the ASCII equivalent characters * But watch out for the bad unprintable ones... */ - for (j = 0; j < 16; j++) { if (i + j >= count) { acpi_os_printf ("\n"); diff -Nru a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c --- a/drivers/acpi/utilities/utdelete.c Sun Jun 2 18:44:57 2002 +++ b/drivers/acpi/utilities/utdelete.c Sun Jun 2 18:44:57 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: utdelete - object deletion and reference count utilities - * $Revision: 88 $ + * $Revision: 90 $ * ******************************************************************************/ @@ -27,8 +27,6 @@ #include "acpi.h" #include "acinterp.h" #include "acnamesp.h" -#include "actables.h" -#include "acparser.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME ("utdelete") @@ -114,7 +112,7 @@ object, object->mutex.semaphore)); acpi_ex_unlink_mutex (object); - acpi_os_delete_semaphore (object->mutex.semaphore); + (void) acpi_os_delete_semaphore (object->mutex.semaphore); break; @@ -123,7 +121,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Event %p, Semaphore %p\n", object, object->event.semaphore)); - acpi_os_delete_semaphore (object->event.semaphore); + (void) acpi_os_delete_semaphore (object->event.semaphore); object->event.semaphore = NULL; break; @@ -135,7 +133,7 @@ /* Delete the method semaphore if it exists */ if (object->method.semaphore) { - acpi_os_delete_semaphore (object->method.semaphore); + (void) acpi_os_delete_semaphore (object->method.semaphore); object->method.semaphore = NULL; } break; @@ -205,14 +203,14 @@ * * PARAMETERS: *Obj_list - Pointer to the list to be deleted * - * RETURN: Status - the status of the call + * RETURN: None * * DESCRIPTION: This function deletes an internal object list, including both * simple objects and package objects * ******************************************************************************/ -acpi_status +void acpi_ut_delete_internal_object_list ( acpi_operand_object **obj_list) { @@ -231,7 +229,7 @@ /* Free the combined parameter pointer list and object array */ ACPI_MEM_FREE (obj_list); - return_ACPI_STATUS (AE_OK); + return_VOID; } @@ -411,7 +409,7 @@ status = acpi_ut_create_update_state_and_push (object->device.addr_handler, action, &state_list); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto error_exit; } acpi_ut_update_ref_count (object->device.sys_handler, action); @@ -448,7 +446,7 @@ status = acpi_ut_create_update_state_and_push ( object->package.elements[i], action, &state_list); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto error_exit; } } break; @@ -458,9 +456,8 @@ status = acpi_ut_create_update_state_and_push ( object->buffer_field.buffer_obj, action, &state_list); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto error_exit; } break; @@ -470,7 +467,7 @@ status = acpi_ut_create_update_state_and_push ( object->field.region_obj, action, &state_list); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto error_exit; } break; @@ -480,13 +477,13 @@ status = acpi_ut_create_update_state_and_push ( object->bank_field.bank_obj, action, &state_list); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto error_exit; } status = acpi_ut_create_update_state_and_push ( object->bank_field.region_obj, action, &state_list); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto error_exit; } break; @@ -496,19 +493,20 @@ status = acpi_ut_create_update_state_and_push ( object->index_field.index_obj, action, &state_list); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto error_exit; } status = acpi_ut_create_update_state_and_push ( object->index_field.data_obj, action, &state_list); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto error_exit; } break; case ACPI_TYPE_REGION: case INTERNAL_TYPE_REFERENCE: + default: /* No subobjects */ break; @@ -527,6 +525,14 @@ } return_ACPI_STATUS (AE_OK); + + +error_exit: + + ACPI_REPORT_ERROR (("Could not update object reference count, %s\n", + acpi_format_exception (status))); + + return_ACPI_STATUS (status); } @@ -561,7 +567,7 @@ /* * We have a valid ACPI internal object, now increment the reference count */ - acpi_ut_update_object_reference (object, REF_INCREMENT); + (void) acpi_ut_update_object_reference (object, REF_INCREMENT); return_VOID; } @@ -610,7 +616,7 @@ * if the reference count becomes 0. (Must also decrement the ref count * of all subobjects!) */ - acpi_ut_update_object_reference (object, REF_DECREMENT); + (void) acpi_ut_update_object_reference (object, REF_DECREMENT); return_VOID; } diff -Nru a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c --- a/drivers/acpi/utilities/uteval.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/utilities/uteval.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: uteval - Object evaluation - * $Revision: 38 $ + * $Revision: 39 $ * *****************************************************************************/ @@ -69,11 +69,11 @@ if (ACPI_FAILURE (status)) { if (status == AE_NOT_FOUND) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s on %4.4s was not found\n", - object_name, (char *) &device_node->name)); + object_name, device_node->name.ascii)); } else { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s on %4.4s failed with status %s\n", - object_name, (char *) &device_node->name, + object_name, device_node->name.ascii, acpi_format_exception (status))); } @@ -148,11 +148,11 @@ if (ACPI_FAILURE (status)) { if (status == AE_NOT_FOUND) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "_HID on %4.4s was not found\n", - (char *) &device_node->name)); + device_node->name.ascii)); } else { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "_HID on %4.4s failed %s\n", - (char *) &device_node->name, acpi_format_exception (status))); + device_node->name.ascii, acpi_format_exception (status))); } return_ACPI_STATUS (status); @@ -231,11 +231,11 @@ if (ACPI_FAILURE (status)) { if (status == AE_NOT_FOUND) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "_CID on %4.4s was not found\n", - (char *)&device_node->name)); + device_node->name.ascii)); } else { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "_CID on %4.4s failed %s\n", - (char *)&device_node->name, acpi_format_exception (status))); + device_node->name.ascii, acpi_format_exception (status))); } return_ACPI_STATUS (status); @@ -325,12 +325,12 @@ if (ACPI_FAILURE (status)) { if (status == AE_NOT_FOUND) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "_UID on %4.4s was not found\n", - (char *) &device_node->name)); + device_node->name.ascii)); } else { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "_UID on %4.4s failed %s\n", - (char *) &device_node->name, acpi_format_exception (status))); + device_node->name.ascii, acpi_format_exception (status))); } return (status); @@ -411,7 +411,7 @@ if (AE_NOT_FOUND == status) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "_STA on %4.4s was not found, assuming present.\n", - (char *) &device_node->name)); + device_node->name.ascii)); *flags = 0x0F; status = AE_OK; @@ -419,7 +419,7 @@ else if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "_STA on %4.4s failed %s\n", - (char *) &device_node->name, + device_node->name.ascii, acpi_format_exception (status))); } diff -Nru a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c --- a/drivers/acpi/utilities/utglobal.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/utilities/utglobal.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: utglobal - Global variables for the ACPI subsystem - * $Revision: 155 $ + * $Revision: 161 $ * *****************************************************************************/ @@ -26,11 +26,7 @@ #define DEFINE_ACPI_GLOBALS #include "acpi.h" -#include "acevents.h" #include "acnamesp.h" -#include "acinterp.h" -#include "amlcode.h" - #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME ("utglobal") @@ -180,15 +176,15 @@ */ const acpi_predefined_names acpi_gbl_pre_defined_names[] = -{ {"_GPE", INTERNAL_TYPE_DEF_ANY}, - {"_PR_", INTERNAL_TYPE_DEF_ANY}, - {"_SB_", ACPI_TYPE_DEVICE}, - {"_SI_", INTERNAL_TYPE_DEF_ANY}, - {"_TZ_", INTERNAL_TYPE_DEF_ANY}, +{ {"_GPE", INTERNAL_TYPE_DEF_ANY, NULL}, + {"_PR_", INTERNAL_TYPE_DEF_ANY, NULL}, + {"_SB_", ACPI_TYPE_DEVICE, NULL}, + {"_SI_", INTERNAL_TYPE_DEF_ANY, NULL}, + {"_TZ_", INTERNAL_TYPE_DEF_ANY, NULL}, {"_REV", ACPI_TYPE_INTEGER, "2"}, {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, {"_GL_", ACPI_TYPE_MUTEX, "0"}, - {NULL, ACPI_TYPE_ANY} /* Table terminator */ + {NULL, ACPI_TYPE_ANY, NULL} /* Table terminator */ }; @@ -243,9 +239,9 @@ /* Hex to ASCII conversion table */ -const NATIVE_CHAR acpi_gbl_hex_to_ascii[] = +static const NATIVE_CHAR acpi_gbl_hex_to_ascii[] = {'0','1','2','3','4','5','6','7', - '8','9','A','B','C','D','E','F'}; + '8','9','A','B','C','D','E','F'}; /***************************************************************************** * @@ -261,7 +257,7 @@ * ****************************************************************************/ -u8 +char acpi_ut_hex_to_ascii_char ( acpi_integer integer, u32 position) @@ -361,7 +357,7 @@ /* Region type decoding */ -const NATIVE_CHAR *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = +static const NATIVE_CHAR *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { "System_memory", "System_iO", @@ -407,7 +403,7 @@ /* Event type decoding */ -const NATIVE_CHAR *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = +static const NATIVE_CHAR *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = { "PM_Timer", "Global_lock", @@ -431,7 +427,7 @@ } -#ifdef ACPI_DEBUG +#if defined(ACPI_DEBUG) || defined(ENABLE_DEBUGGER) /* * Strings and procedures used for debug only @@ -545,16 +541,21 @@ } +/* Various strings for future use */ + +#if 0 +#include "amlcode.h" + /* Data used in keeping track of fields */ -const NATIVE_CHAR *acpi_gbl_FEnames[NUM_FIELD_NAMES] = +static const NATIVE_CHAR *acpi_gbl_FEnames[NUM_FIELD_NAMES] = { "skip", "?access?" }; /* FE = Field Element */ -const NATIVE_CHAR *acpi_gbl_match_ops[NUM_MATCH_OPS] = +static const NATIVE_CHAR *acpi_gbl_match_ops[NUM_MATCH_OPS] = { "Error", "MTR", @@ -568,7 +569,7 @@ /* Access type decoding */ -const NATIVE_CHAR *acpi_gbl_access_types[NUM_ACCESS_TYPES] = +static const NATIVE_CHAR *acpi_gbl_access_types[NUM_ACCESS_TYPES] = { "Any_acc", "Byte_acc", @@ -581,12 +582,13 @@ /* Update rule decoding */ -const NATIVE_CHAR *acpi_gbl_update_rules[NUM_UPDATE_RULES] = +static const NATIVE_CHAR *acpi_gbl_update_rules[NUM_UPDATE_RULES] = { "Preserve", "Write_as_ones", "Write_as_zeros" }; +#endif /* Future use */ #endif @@ -670,6 +672,9 @@ acpi_gbl_next_method_owner_id = ACPI_FIRST_METHOD_ID; } break; + + default: + break; } (void) acpi_ut_release_mutex (ACPI_MTX_CACHES); @@ -702,15 +707,15 @@ ACPI_MEMSET (acpi_gbl_memory_lists, 0, sizeof (ACPI_MEMORY_LIST) * ACPI_NUM_MEM_LISTS); acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].link_offset = (u16) ACPI_PTR_DIFF (&(((acpi_generic_state *) NULL)->common.next), NULL); - acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].link_offset = (u16) ACPI_PTR_DIFF (&(((acpi_parse_object *) NULL)->next), NULL); - acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].link_offset = (u16) ACPI_PTR_DIFF (&(((acpi_parse2_object *) NULL)->next), NULL); + acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].link_offset = (u16) ACPI_PTR_DIFF (&(((acpi_parse_object *) NULL)->common.next), NULL); + acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].link_offset = (u16) ACPI_PTR_DIFF (&(((acpi_parse_object *) NULL)->common.next), NULL); acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].link_offset = (u16) ACPI_PTR_DIFF (&(((acpi_operand_object *) NULL)->cache.next), NULL); acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].link_offset = (u16) ACPI_PTR_DIFF (&(((acpi_walk_state *) NULL)->next), NULL); acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].object_size = sizeof (acpi_namespace_node); acpi_gbl_memory_lists[ACPI_MEM_LIST_STATE].object_size = sizeof (acpi_generic_state); - acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].object_size = sizeof (acpi_parse_object); - acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].object_size = sizeof (acpi_parse2_object); + acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE].object_size = sizeof (ACPI_PARSE_OBJ_COMMON); + acpi_gbl_memory_lists[ACPI_MEM_LIST_PSNODE_EXT].object_size = sizeof (ACPI_PARSE_OBJ_NAMED); acpi_gbl_memory_lists[ACPI_MEM_LIST_OPERAND].object_size = sizeof (acpi_operand_object); acpi_gbl_memory_lists[ACPI_MEM_LIST_WALK].object_size = sizeof (acpi_walk_state); @@ -753,6 +758,7 @@ acpi_gbl_sys_notify.handler = NULL; acpi_gbl_drv_notify.handler = NULL; + acpi_gbl_init_handler = NULL; /* Global "typed" ACPI table pointers */ @@ -802,7 +808,7 @@ #ifdef ACPI_DEBUG - acpi_gbl_lowest_stack_pointer = ACPI_UINT32_MAX; + acpi_gbl_lowest_stack_pointer = ACPI_SIZE_MAX; #endif return_VOID; diff -Nru a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c --- a/drivers/acpi/utilities/utinit.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/utilities/utinit.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: utinit - Common ACPI subsystem initialization - * $Revision: 109 $ + * $Revision: 112 $ * *****************************************************************************/ @@ -25,7 +25,6 @@ #include "acpi.h" -#include "achware.h" #include "acnamesp.h" #include "acevents.h" @@ -56,7 +55,7 @@ { ACPI_REPORT_WARNING ( - ("Invalid FADT value %s=%lX at offset %lX FADT=%p\n", + ("Invalid FADT value %s=%X at offset %X FADT=%p\n", register_name, value, offset, acpi_gbl_FADT)); } @@ -181,7 +180,7 @@ * ******************************************************************************/ -acpi_status +void acpi_ut_subsystem_shutdown (void) { @@ -191,7 +190,7 @@ if (acpi_gbl_shutdown) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "ACPI Subsystem is already terminated\n")); - return_ACPI_STATUS (AE_OK); + return_VOID; } /* Subsystem appears active, go ahead and shut it down */ @@ -213,7 +212,7 @@ /* Purge the local caches */ - acpi_purge_cached_objects (); + (void) acpi_purge_cached_objects (); /* Debug only - display leftover memory allocation, if any */ @@ -221,7 +220,7 @@ acpi_ut_dump_allocations (ACPI_UINT32_MAX, NULL); #endif - return_ACPI_STATUS (AE_OK); + return_VOID; } diff -Nru a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c --- a/drivers/acpi/utilities/utmath.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/utilities/utmath.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: utmath - Integer math support routines - * $Revision: 10 $ + * $Revision: 11 $ * ******************************************************************************/ @@ -193,7 +193,7 @@ */ partial1 = quotient.part.lo * divisor.part.hi; partial2.full = (acpi_integer) quotient.part.lo * divisor.part.lo; - partial3.full = partial2.part.hi + partial1; + partial3.full = (acpi_integer) partial2.part.hi + partial1; remainder.part.hi = partial3.part.lo; remainder.part.lo = partial2.part.lo; @@ -213,8 +213,8 @@ } remainder.full = remainder.full - dividend.full; - remainder.part.hi = -((s32) remainder.part.hi); - remainder.part.lo = -((s32) remainder.part.lo); + remainder.part.hi = (u32) -((s32) remainder.part.hi); + remainder.part.lo = (u32) -((s32) remainder.part.lo); if (remainder.part.lo) { remainder.part.hi--; diff -Nru a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c --- a/drivers/acpi/utilities/utmisc.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/utilities/utmisc.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: utmisc - common utility procedures - * $Revision: 67 $ + * $Revision: 75 $ * ******************************************************************************/ @@ -25,18 +25,84 @@ #include "acpi.h" -#include "acevents.h" -#include "achware.h" #include "acnamesp.h" -#include "acinterp.h" #include "amlcode.h" -#include "acdebug.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME ("utmisc") +/******************************************************************************* + * + * FUNCTION: Acpi_ut_dword_byte_swap + * + * PARAMETERS: Value - Value to be converted + * + * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes) + * + ******************************************************************************/ + +u32 +acpi_ut_dword_byte_swap ( + u32 value) +{ + union { + u32 value; + u8 bytes[4]; + } out; + + union { + u32 value; + u8 bytes[4]; + } in; + + + ACPI_FUNCTION_ENTRY (); + + + in.value = value; + + out.bytes[0] = in.bytes[3]; + out.bytes[1] = in.bytes[2]; + out.bytes[2] = in.bytes[1]; + out.bytes[3] = in.bytes[0]; + + return (out.value); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_set_integer_width + * + * PARAMETERS: Revision From DSDT header + * + * RETURN: None + * + * DESCRIPTION: Set the global integer bit width based upon the revision + * of the DSDT. For Revision 1 and 0, Integers are 32 bits. + * For Revision 2 and above, Integers are 64 bits. Yes, this + * makes a difference. + * + ******************************************************************************/ + +void +acpi_ut_set_integer_width ( + u8 revision) +{ + + if (revision <= 1) { + acpi_gbl_integer_bit_width = 32; + acpi_gbl_integer_byte_width = 4; + } + else { + acpi_gbl_integer_bit_width = 64; + acpi_gbl_integer_byte_width = 8; + } +} + + #ifdef ACPI_DEBUG /******************************************************************************* * @@ -145,6 +211,152 @@ /******************************************************************************* * + * FUNCTION: Acpi_ut_strtoul64 + * + * PARAMETERS: String - Null terminated string + * Terminater - Where a pointer to the terminating byte is returned + * Base - Radix of the string + * + * RETURN: Converted value + * + * DESCRIPTION: Convert a string into an unsigned value. + * + ******************************************************************************/ +#define NEGATIVE 1 +#define POSITIVE 0 + +acpi_status +acpi_ut_strtoul64 ( + NATIVE_CHAR *string, + u32 base, + acpi_integer *ret_integer) +{ + u32 index; + acpi_integer return_value = 0; + acpi_status status = AE_OK; + acpi_integer dividend; + acpi_integer quotient; + + + *ret_integer = 0; + + switch (base) { + case 0: + case 8: + case 10: + case 16: + break; + + default: + /* + * The specified Base parameter is not in the domain of + * this function: + */ + return (AE_BAD_PARAMETER); + } + + /* + * skip over any white space in the buffer: + */ + while (ACPI_IS_SPACE (*string) || *string == '\t') { + ++string; + } + + /* + * If the input parameter Base is zero, then we need to + * determine if it is octal, decimal, or hexadecimal: + */ + if (base == 0) { + if (*string == '0') { + if (ACPI_TOLOWER (*(++string)) == 'x') { + base = 16; + ++string; + } + else { + base = 8; + } + } + else { + base = 10; + } + } + + /* + * For octal and hexadecimal bases, skip over the leading + * 0 or 0x, if they are present. + */ + if (base == 8 && *string == '0') { + string++; + } + + if (base == 16 && + *string == '0' && + ACPI_TOLOWER (*(++string)) == 'x') { + string++; + } + + /* Main loop: convert the string to an unsigned long */ + + while (*string) { + if (ACPI_IS_DIGIT (*string)) { + index = ((u8) *string) - '0'; + } + else { + index = (u8) ACPI_TOUPPER (*string); + if (ACPI_IS_UPPER ((char) index)) { + index = index - 'A' + 10; + } + else { + goto error_exit; + } + } + + if (index >= base) { + goto error_exit; + } + + /* Check to see if value is out of range: */ + + dividend = ACPI_INTEGER_MAX - (acpi_integer) index; + (void) acpi_ut_short_divide (÷nd, base, "ient, NULL); + if (return_value > quotient) { + goto error_exit; + } + + return_value *= base; + return_value += index; + ++string; + } + + *ret_integer = return_value; + return (status); + + +error_exit: + switch (base) { + case 8: + status = AE_BAD_OCTAL_CONSTANT; + break; + + case 10: + status = AE_BAD_DECIMAL_CONSTANT; + break; + + case 16: + status = AE_BAD_HEX_CONSTANT; + break; + + default: + /* Base validated above */ + break; + } + + return (status); +} + + +/******************************************************************************* + * * FUNCTION: Acpi_ut_strupr * * PARAMETERS: Src_string - The source string to convert to @@ -239,7 +451,7 @@ * Delete each predefined mutex object */ for (i = 0; i < NUM_MTX; i++) { - acpi_ut_delete_mutex (i); + (void) acpi_ut_delete_mutex (i); } return_VOID; @@ -933,6 +1145,10 @@ source_object->common.type = ACPI_TYPE_INTEGER; source_object->integer.value = ACPI_INTEGER_MAX; break; + + default: + /* Other types not supported */ + return (AE_SUPPORT); } } break; @@ -945,6 +1161,9 @@ info->num_packages++; state->pkg.this_target_obj = NULL; break; + + default: + return (AE_BAD_PARAMETER); } return (AE_OK); @@ -1040,7 +1259,7 @@ * case below. */ if ((!this_source_obj) || - (ACPI_GET_DESCRIPTOR_TYPE (this_source_obj) != ACPI_DESC_TYPE_INTERNAL) || + (ACPI_GET_DESCRIPTOR_TYPE (this_source_obj) != ACPI_DESC_TYPE_OPERAND) || (this_source_obj->common.type != ACPI_TYPE_PACKAGE)) { status = walk_callback (ACPI_COPY_TYPE_SIMPLE, this_source_obj, state, context); diff -Nru a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c --- a/drivers/acpi/utilities/utobject.c Sun Jun 2 18:44:58 2002 +++ b/drivers/acpi/utilities/utobject.c Sun Jun 2 18:44:58 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: utobject - ACPI object create/delete/size/cache routines - * $Revision: 68 $ + * $Revision: 73 $ * *****************************************************************************/ @@ -25,9 +25,7 @@ #include "acpi.h" -#include "acinterp.h" #include "acnamesp.h" -#include "actables.h" #include "amlcode.h" @@ -97,6 +95,10 @@ object->common.next_object = second_object; break; + + default: + /* All others have no secondary object */ + break; } /* Save the object type in the object descriptor */ @@ -142,7 +144,7 @@ /* Check the descriptor type field */ switch (ACPI_GET_DESCRIPTOR_TYPE (object)) { - case ACPI_DESC_TYPE_INTERNAL: + case ACPI_DESC_TYPE_OPERAND: /* The object appears to be a valid acpi_operand_object */ @@ -210,10 +212,10 @@ /* Mark the descriptor type */ - ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL); + ACPI_SET_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_OPERAND); ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p Size %X\n", - object, sizeof (acpi_operand_object))); + object, (u32) sizeof (acpi_operand_object))); return_PTR (object); } @@ -240,7 +242,7 @@ /* Object must be an acpi_operand_object */ - if (ACPI_GET_DESCRIPTOR_TYPE (object) != ACPI_DESC_TYPE_INTERNAL) { + if (ACPI_GET_DESCRIPTOR_TYPE (object) != ACPI_DESC_TYPE_OPERAND) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Obj %p is not an ACPI object\n", object)); return_VOID; @@ -337,13 +339,13 @@ case ACPI_TYPE_STRING: - length += internal_object->string.length + 1; + length += (ACPI_SIZE) internal_object->string.length + 1; break; case ACPI_TYPE_BUFFER: - length += internal_object->buffer.length; + length += (ACPI_SIZE) internal_object->buffer.length; break; @@ -461,6 +463,13 @@ info->num_packages++; state->pkg.this_target_obj = NULL; break; + + + default: + + /* No other types allowed */ + + return (AE_BAD_PARAMETER); } return (status); @@ -512,7 +521,7 @@ * Round up to the next machine word. */ info.length += ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (acpi_object)) * - info.num_packages; + (ACPI_SIZE) info.num_packages; /* Return the total package length */ @@ -546,7 +555,7 @@ ACPI_FUNCTION_ENTRY (); - if ((ACPI_GET_DESCRIPTOR_TYPE (internal_object) == ACPI_DESC_TYPE_INTERNAL) && + if ((ACPI_GET_DESCRIPTOR_TYPE (internal_object) == ACPI_DESC_TYPE_OPERAND) && (internal_object->common.type == ACPI_TYPE_PACKAGE)) { status = acpi_ut_get_package_object_size (internal_object, obj_length); } diff -Nru a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c --- a/drivers/acpi/utilities/utxface.c Sun Jun 2 18:44:56 2002 +++ b/drivers/acpi/utilities/utxface.c Sun Jun 2 18:44:56 2002 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: utxface - External interfaces for "global" ACPI functions - * $Revision: 92 $ + * $Revision: 96 $ * *****************************************************************************/ @@ -26,15 +26,10 @@ #include "acpi.h" #include "acevents.h" -#include "achware.h" #include "acnamesp.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acdebug.h" -#include "acexcep.h" #include "acparser.h" #include "acdispat.h" - +#include "acdebug.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME ("utxface") @@ -102,7 +97,7 @@ /* If configured, initialize the AML debugger */ - ACPI_DEBUGGER_EXEC (acpi_db_initialize ()); + ACPI_DEBUGGER_EXEC (status = acpi_db_initialize ()); return_ACPI_STATUS (status); } @@ -139,7 +134,7 @@ if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n")); - status = acpi_ev_install_default_address_space_handlers (); + status = acpi_ev_init_address_spaces (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -251,6 +246,9 @@ acpi_status acpi_terminate (void) { + acpi_status status; + + ACPI_FUNCTION_TRACE ("Acpi_terminate"); @@ -277,10 +275,8 @@ /* Now we can shutdown the OS-dependent layer */ - acpi_os_terminate (); - - - return_ACPI_STATUS (AE_OK); + status = acpi_os_terminate (); + return_ACPI_STATUS (status); } @@ -396,6 +392,39 @@ } return_ACPI_STATUS (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_install_initialization_handler + * + * PARAMETERS: Handler - Callback procedure + * + * RETURN: Status + * + * DESCRIPTION: Install an initialization handler + * + * TBD: When a second function is added, must save the Function also. + * + ****************************************************************************/ + +acpi_status +acpi_install_initialization_handler ( + ACPI_INIT_HANDLER handler, + u32 function) +{ + + if (!handler) { + return (AE_BAD_PARAMETER); + } + + if (acpi_gbl_init_handler) { + return (AE_ALREADY_EXISTS); + } + + acpi_gbl_init_handler = handler; + return AE_OK; } diff -Nru a/drivers/acpi/utils.c b/drivers/acpi/utils.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/acpi/utils.c Sun Jun 2 18:44:57 2002 @@ -0,0 +1,460 @@ +/* + * acpi_utils.c - ACPI Utility Functions ($Revision: 5 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include "acpi_bus.h" +#include "acpi_drivers.h" + + +#define _COMPONENT ACPI_BUS_COMPONENT +ACPI_MODULE_NAME ("acpi_utils") + + +/* -------------------------------------------------------------------------- + Object Evaluation Helpers + -------------------------------------------------------------------------- */ + +#ifdef ACPI_DEBUG +#define acpi_util_eval_error(h,p,s) {\ + char prefix[80] = {'\0'};\ + acpi_buffer buffer = {sizeof(prefix), prefix};\ + acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\ + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",\ + (char *) prefix, p, acpi_format_exception(s))); } +#else +#define acpi_util_eval_error(h,p,s) +#endif + + +acpi_status +acpi_extract_package ( + acpi_object *package, + acpi_buffer *format, + acpi_buffer *buffer) +{ + u32 size_required = 0; + u32 tail_offset = 0; + char *format_string = NULL; + u32 format_count = 0; + u32 i = 0; + u8 *head = NULL; + u8 *tail = NULL; + + ACPI_FUNCTION_TRACE("acpi_extract_package"); + + if (!package || (package->type != ACPI_TYPE_PACKAGE) || (package->package.count < 1)) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'package' argument\n")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (!format || !format->pointer || (format->length < 1)) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'format' argument\n")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (!buffer) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid 'buffer' argument\n")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + format_count = (format->length/sizeof(char)) - 1; + if (format_count > package->package.count) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Format specifies more objects [%d] than exist in package [%d].", format_count, package->package.count)); + return_ACPI_STATUS(AE_BAD_DATA); + } + + format_string = (char*)format->pointer; + + /* + * Calculate size_required. + */ + for (i=0; ipackage.elements[i]); + + if (!element) { + return_ACPI_STATUS(AE_BAD_DATA); + } + + switch (element->type) { + + case ACPI_TYPE_INTEGER: + switch (format_string[i]) { + case 'N': + size_required += sizeof(acpi_integer); + tail_offset += sizeof(acpi_integer); + break; + case 'S': + size_required += sizeof(char*) + sizeof(acpi_integer) + sizeof(char); + tail_offset += sizeof(char*); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid package element [%d]: got number, expecing [%c].\n", i, format_string[i])); + return_ACPI_STATUS(AE_BAD_DATA); + break; + } + break; + + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + switch (format_string[i]) { + case 'S': + size_required += sizeof(char*) + (element->string.length * sizeof(char)) + sizeof(char); + tail_offset += sizeof(char*); + break; + case 'B': + size_required += sizeof(u8*) + (element->buffer.length * sizeof(u8)); + tail_offset += sizeof(u8*); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid package element [%d] got string/buffer, expecing [%c].\n", i, format_string[i])); + return_ACPI_STATUS(AE_BAD_DATA); + break; + } + break; + + case ACPI_TYPE_PACKAGE: + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unsupported element at index=%d\n", i)); + /* TBD: handle nested packages... */ + return_ACPI_STATUS(AE_SUPPORT); + break; + } + } + + /* + * Validate output buffer. + */ + if (buffer->length < size_required) { + buffer->length = size_required; + return_ACPI_STATUS(AE_BUFFER_OVERFLOW); + } + else if (buffer->length != size_required || !buffer->pointer) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + head = buffer->pointer; + tail = buffer->pointer + tail_offset; + + /* + * Extract package data. + */ + for (i=0; ipackage.elements[i]); + + if (!element) { + return_ACPI_STATUS(AE_BAD_DATA); + } + + switch (element->type) { + + case ACPI_TYPE_INTEGER: + switch (format_string[i]) { + case 'N': + *((acpi_integer*)head) = element->integer.value; + head += sizeof(acpi_integer); + break; + case 'S': + pointer = (u8**)head; + *pointer = tail; + *((acpi_integer*)tail) = element->integer.value; + head += sizeof(acpi_integer*); + tail += sizeof(acpi_integer); + /* NULL terminate string */ + *tail = (char)0; + tail += sizeof(char); + break; + default: + /* Should never get here */ + break; + } + break; + + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + switch (format_string[i]) { + case 'S': + pointer = (u8**)head; + *pointer = tail; + memcpy(tail, element->string.pointer, element->string.length); + head += sizeof(char*); + tail += element->string.length * sizeof(char); + /* NULL terminate string */ + *tail = (char)0; + tail += sizeof(char); + break; + case 'B': + pointer = (u8**)head; + *pointer = tail; + memcpy(tail, element->buffer.pointer, element->buffer.length); + head += sizeof(u8*); + tail += element->buffer.length * sizeof(u8); + break; + default: + /* Should never get here */ + break; + } + break; + + case ACPI_TYPE_PACKAGE: + /* TBD: handle nested packages... */ + default: + /* Should never get here */ + break; + } + } + + return_ACPI_STATUS(AE_OK); +} + + +acpi_status +acpi_evaluate ( + acpi_handle handle, + acpi_string pathname, + acpi_object_list *arguments, + acpi_buffer *buffer) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_evaluate"); + + /* If caller provided a buffer it must be unallocated/zero'd. */ + if (buffer && (buffer->length != 0 || buffer->pointer)) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + /* + * Evalute object. The first attempt is just to get the size of the + * object data (that is unless there's no return data); the second + * gets the data. + */ + status = acpi_evaluate_object(handle, pathname, arguments, buffer); + + if (ACPI_SUCCESS(status)) { + return_ACPI_STATUS(status); + } + + else if (buffer && (status == AE_BUFFER_OVERFLOW)) { + + /* Gotta allocate - CALLER MUST FREE! */ + buffer->pointer = kmalloc(buffer->length, GFP_KERNEL); + if (!buffer->pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + memset(buffer->pointer, 0, buffer->length); + + /* Re-evaluate - this time it should work. */ + status = acpi_evaluate_object(handle, pathname, arguments, + buffer); + } + + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) + acpi_util_eval_error(handle, pathname, status); + if (buffer && buffer->pointer) { + kfree(buffer->pointer); + buffer->length = 0; + } + } + + return_ACPI_STATUS(status); +} + + +acpi_status +acpi_evaluate_integer ( + acpi_handle handle, + acpi_string pathname, + acpi_object_list *arguments, + unsigned long *data) +{ + acpi_status status = AE_OK; + acpi_object element; + acpi_buffer buffer = {sizeof(acpi_object), &element}; + + ACPI_FUNCTION_TRACE("acpi_evaluate_integer"); + + if (!data) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + status = acpi_evaluate_object(handle, pathname, arguments, &buffer); + if (ACPI_FAILURE(status)) { + acpi_util_eval_error(handle, pathname, status); + return_ACPI_STATUS(status); + } + + if (element.type != ACPI_TYPE_INTEGER) { + acpi_util_eval_error(handle, pathname, AE_BAD_DATA); + return_ACPI_STATUS(AE_BAD_DATA); + } + + *data = element.integer.value; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data)); + + return_ACPI_STATUS(AE_OK); +} + + +#if 0 +acpi_status +acpi_evaluate_string ( + acpi_handle handle, + acpi_string pathname, + acpi_object_list *arguments, + acpi_string *data) +{ + acpi_status status = AE_OK; + acpi_object *element = NULL; + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + + ACPI_FUNCTION_TRACE("acpi_evaluate_string"); + + if (!data) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + status = acpi_evaluate_object(handle, pathname, arguments, &buffer); + if (ACPI_FAILURE(status)) { + acpi_util_eval_error(handle, pathname, status); + return_ACPI_STATUS(status); + } + + element = (acpi_object *) buffer.pointer; + + if ((element->type != ACPI_TYPE_STRING) + || (element->type != ACPI_TYPE_BUFFER) + || !element->string.length) { + acpi_util_eval_error(handle, pathname, AE_BAD_DATA); + return_ACPI_STATUS(AE_BAD_DATA); + } + + *data = kmalloc(element->string.length + 1, GFP_KERNEL); + if (!data) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Memory allocation error\n")); + return_VALUE(-ENOMEM); + } + memset(*data, 0, element->string.length + 1); + + memcpy(*data, element->string.pointer, element->string.length); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%s]\n", *data)); + + return_ACPI_STATUS(AE_OK); +} +#endif + + +acpi_status +acpi_evaluate_reference ( + acpi_handle handle, + acpi_string pathname, + acpi_object_list *arguments, + struct acpi_handle_list *list) +{ + acpi_status status = AE_OK; + acpi_object *package = NULL; + acpi_object *element = NULL; + acpi_buffer buffer = {0, NULL}; + u32 i = 0; + + ACPI_FUNCTION_TRACE("acpi_evaluate_reference"); + + if (!list) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Evaluate object. */ + + status = acpi_evaluate(handle, pathname, arguments, &buffer); + if (ACPI_FAILURE(status)) + goto end; + + package = (acpi_object *) buffer.pointer; + + if (!package || (package->type != ACPI_TYPE_PACKAGE) + || (package->package.count == 0)) { + status = AE_BAD_DATA; + acpi_util_eval_error(handle, pathname, status); + goto end; + } + + /* Allocate list - CALLER MUST FREE! */ + list->count = package->package.count; + if (list->count > 10) { + return AE_NO_MEMORY; + } + /* TBD: dynamically allocate */ + /* + list->handles = kmalloc(sizeof(acpi_handle)*(list->count), GFP_KERNEL); + if (!list->handles) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + memset(list->handles, 0, sizeof(acpi_handle)*(list->count)); + */ + + /* Parse package data. */ + + for (i = 0; i < list->count; i++) { + + element = &(package->package.elements[i]); + + if (!element || (element->type != ACPI_TYPE_STRING)) { + status = AE_BAD_DATA; + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid element in package (not a device reference)\n")); + acpi_util_eval_error(handle, pathname, status); + break; + } + + /* Convert reference (e.g. "\_PR_.CPU_") to acpi_handle. */ + + status = acpi_get_handle(handle, element->string.pointer, + &(list->handles[i])); + if (ACPI_FAILURE(status)) { + status = AE_BAD_DATA; + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to resolve device reference [%s]\n", element->string.pointer)); + acpi_util_eval_error(handle, pathname, status); + break; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resolved reference [%s]->[%p]\n", element->string.pointer, list->handles[i])); + } + +end: + if (ACPI_FAILURE(status)) { + list->count = 0; + //kfree(list->handles); + } + + kfree(buffer.pointer); + + return_ACPI_STATUS(status); +} + + diff -Nru a/drivers/base/base.h b/drivers/base/base.h --- a/drivers/base/base.h Sun Jun 2 18:44:57 2002 +++ b/drivers/base/base.h Sun Jun 2 18:44:57 2002 @@ -17,3 +17,6 @@ extern void device_remove_dir(struct device * dev); extern int device_bus_link(struct device * dev); + +extern int driver_bind(struct device_driver * drv); +extern void driver_unbind(struct device_driver * drv); diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c --- a/drivers/base/bus.c Sun Jun 2 18:44:56 2002 +++ b/drivers/base/bus.c Sun Jun 2 18:44:56 2002 @@ -13,6 +13,7 @@ #include #include #include +#include #include "base.h" static LIST_HEAD(bus_driver_list); @@ -23,6 +24,91 @@ }; /** + * bus_for_each_dev - walk list of devices and do something to each + * @bus: bus in question + * @data: data for the callback + * @callback: caller-defined action to perform on each device + * + * Why do we do this? So we can guarantee proper locking and reference + * counting on devices as we touch each one. + * + * Algorithm: + * Take the bus lock and get the first node in the list. We increment + * the reference count and unlock the bus. If we have a device from a + * previous iteration, we decrement the reference count. + * After we call the callback, we get the next node in the list and loop. + * At the end, if @dev is not null, we still have it pinned, so we need + * to let it go. + */ +int bus_for_each_dev(struct bus_type * bus, void * data, + int (*callback)(struct device * dev, void * data)) +{ + struct device * next; + struct device * dev = NULL; + struct list_head * node; + int error = 0; + + get_bus(bus); + read_lock(&bus->lock); + node = bus->devices.next; + while (node != &bus->devices) { + next = list_entry(node,struct device,bus_list); + get_device(next); + read_unlock(&bus->lock); + + if (dev) + put_device(dev); + dev = next; + if ((error = callback(dev,data))) { + put_device(dev); + break; + } + read_lock(&bus->lock); + node = dev->bus_list.next; + } + read_unlock(&bus->lock); + if (dev) + put_device(dev); + put_bus(bus); + return error; +} + +int bus_for_each_drv(struct bus_type * bus, void * data, + int (*callback)(struct device_driver * drv, void * data)) +{ + struct device_driver * next; + struct device_driver * drv = NULL; + struct list_head * node; + int error = 0; + + /* pin bus in memory */ + get_bus(bus); + + read_lock(&bus->lock); + node = bus->drivers.next; + while (node != &bus->drivers) { + next = list_entry(node,struct device_driver,bus_list); + get_driver(next); + read_unlock(&bus->lock); + + if (drv) + put_driver(drv); + drv = next; + if ((error = callback(drv,data))) { + put_driver(drv); + break; + } + read_lock(&bus->lock); + node = drv->bus_list.next; + } + read_unlock(&bus->lock); + if (drv) + put_driver(drv); + put_bus(bus); + return error; +} + +/** * bus_add_device - add device to bus * @dev: device being added * @@ -119,6 +205,8 @@ core_initcall(bus_init); +EXPORT_SYMBOL(bus_for_each_dev); +EXPORT_SYMBOL(bus_for_each_drv); EXPORT_SYMBOL(bus_add_device); EXPORT_SYMBOL(bus_remove_device); EXPORT_SYMBOL(bus_register); diff -Nru a/drivers/base/core.c b/drivers/base/core.c --- a/drivers/base/core.c Sun Jun 2 18:44:56 2002 +++ b/drivers/base/core.c Sun Jun 2 18:44:56 2002 @@ -23,6 +23,120 @@ spinlock_t device_lock = SPIN_LOCK_UNLOCKED; + +/** + * found_match - do actual binding of device to driver + * @dev: device + * @drv: driver + * + * We're here because the bus's bind callback returned success for this + * pair. We call the driver's probe callback to verify they're really a + * match made in heaven. + * + * In the future, we may want to notify userspace of the binding. (But, + * we might not want to do it here). + * + * We may also want to create a symlink in the driver's directory to the + * device's physical directory. + */ +static int found_match(struct device * dev, struct device_driver * drv) +{ + int error = 0; + + dev->driver = get_driver(drv); + if (drv->probe) + if (drv->probe(dev)) + goto ProbeFailed; + + pr_debug("bound device '%s' to driver '%s'\n", + dev->bus_id,drv->name); + + write_lock(&drv->lock); + list_add_tail(&dev->driver_list,&drv->devices); + write_unlock(&drv->lock); + + goto Done; + + ProbeFailed: + put_driver(drv); + dev->driver = NULL; + Done: + return error; +} + +/** + * bind_device - try to associated device with a driver + * @drv: current driver to try + * @data: device in disguise + * + * This function is used as a callback to bus_for_each_drv. + * It calls the bus's ::bind callback to check if the driver supports + * the device. If so, it calls the found_match() function above to + * take care of all the details. + */ +static int do_device_bind(struct device_driver * drv, void * data) +{ + struct device * dev = (struct device *)data; + int error = 0; + + if (!dev->driver) { + if (drv->bus->bind && drv->bus->bind(dev,drv)) + error = found_match(dev,drv); + } + return error; +} + +static int device_bind(struct device * dev) +{ + int error = 0; + if (dev->bus) + error = bus_for_each_drv(dev->bus,dev,do_device_bind); + return error; +} + +static void device_unbind(struct device * dev) +{ + /* unbind from driver */ + if (dev->driver && dev->driver->remove) + dev->driver->remove(dev); +} + +static int do_driver_bind(struct device * dev, void * data) +{ + struct device_driver * drv = (struct device_driver *)data; + int error = 0; + + if (!dev->driver) { + if (dev->bus->bind && dev->bus->bind(dev,drv)) + error = found_match(dev,drv); + } + return error; +} + +int driver_bind(struct device_driver * drv) +{ + return bus_for_each_dev(drv->bus,drv,do_driver_bind); +} + +static int do_driver_unbind(struct device * dev, void * data) +{ + struct device_driver * drv = (struct device_driver *)data; + lock_device(dev); + if (dev->driver == drv) { + dev->driver = NULL; + unlock_device(dev); + if (drv->remove) + drv->remove(dev); + } else + unlock_device(dev); + return 0; +} + +void driver_unbind(struct device_driver * drv) +{ + driver_for_each_dev(drv,drv,do_driver_unbind); +} + /** * device_register - register a device * @dev: pointer to the device structure @@ -72,6 +186,9 @@ bus_add_device(dev); + /* bind to driver */ + device_bind(dev); + /* notify platform of device entry */ if (platform_notify) platform_notify(dev); @@ -104,14 +221,8 @@ if (platform_notify_remove) platform_notify_remove(dev); + device_unbind(dev); bus_remove_device(dev); - - /* Tell the driver to clean up after itself. - * Note that we likely didn't allocate the device, - * so this is the driver's chance to free that up... - */ - if (dev->driver && dev->driver->remove) - dev->driver->remove(dev,REMOVE_FREE_RESOURCES); /* remove the driverfs directory */ device_remove_dir(dev); diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c --- a/drivers/base/driver.c Sun Jun 2 18:44:58 2002 +++ b/drivers/base/driver.c Sun Jun 2 18:44:58 2002 @@ -8,6 +8,39 @@ #include #include "base.h" + +int driver_for_each_dev(struct device_driver * drv, void * data, int (*callback)(struct device *, void * )) +{ + struct device * next; + struct device * dev = NULL; + struct list_head * node; + int error = 0; + + get_driver(drv); + read_lock(&drv->lock); + node = drv->devices.next; + while (node != &drv->devices) { + next = list_entry(node,struct device,driver_list); + get_device(next); + read_unlock(&drv->lock); + + if (dev) + put_device(dev); + dev = next; + if ((error = callback(dev,data))) { + put_device(dev); + break; + } + read_lock(&drv->lock); + node = dev->driver_list.next; + } + read_unlock(&drv->lock); + if (dev) + put_device(dev); + put_driver(drv); + return error; +} + /** * driver_make_dir - create a driverfs directory for a driver * @drv: driver in question @@ -38,6 +71,7 @@ list_add(&drv->bus_list,&drv->bus->drivers); write_unlock(&drv->bus->lock); driver_make_dir(drv); + driver_bind(drv); put_driver(drv); return 0; } @@ -55,6 +89,7 @@ if (drv->bus) { pr_debug("Unregistering driver '%s' from bus '%s'\n",drv->name,drv->bus->name); + driver_unbind(drv); write_lock(&drv->bus->lock); list_del_init(&drv->bus_list); write_unlock(&drv->bus->lock); @@ -66,5 +101,6 @@ drv->release(drv); } +EXPORT_SYMBOL(driver_for_each_dev); EXPORT_SYMBOL(driver_register); EXPORT_SYMBOL(put_driver); diff -Nru a/drivers/base/interface.c b/drivers/base/interface.c --- a/drivers/base/interface.c Sun Jun 2 18:44:56 2002 +++ b/drivers/base/interface.c Sun Jun 2 18:44:56 2002 @@ -9,75 +9,6 @@ #include #include -/** - * device_read_status - report some device information - * @page: page-sized buffer to write into - * @count: number of bytes requested - * @off: offset into buffer - * @data: device-specific data - * - * Report some human-readable information about the device. - * This includes the name, the bus id, and the current power state. - */ -static ssize_t device_read_status(struct device * dev, char * page, size_t count, loff_t off) -{ - return off ? 0 : sprintf(page,"%s\n",dev->bus_id); -} - -/** - * device_write_status - forward a command to a driver - * @buf: encoded command - * @count: number of bytes in buffer - * @off: offset into buffer to start with - * @data: device-specific data - * - * Send a comamnd to a device driver. - * The following actions are supported: - * probe - scan slot for device - * remove - detach driver from slot - * suspend - perform for entering - * resume - perform for waking device up. - * (See Documentation/driver-model.txt for the theory of an n-stage - * suspend sequence). - */ -static ssize_t device_write_status(struct device * dev, const char* buf, size_t count, loff_t off) -{ - char command[20]; - int num; - int arg = 0; - int error = 0; - - if (off) - return 0; - - /* everything involves dealing with the driver. */ - if (!dev->driver) - return 0; - - num = sscanf(buf,"%10s %d",command,&arg); - - if (!num) - return 0; - - if (!strcmp(command,"probe")) { - if (dev->driver->probe) - error = dev->driver->probe(dev); - - } else if (!strcmp(command,"remove")) { - if (dev->driver->remove) - error = dev->driver->remove(dev,REMOVE_NOTIFY); - } else - error = -EFAULT; - return error < 0 ? error : count; -} - -static struct driver_file_entry device_status_entry = { - name: "status", - mode: S_IWUSR | S_IRUGO, - show: device_read_status, - store: device_write_status, -}; - static ssize_t device_read_name(struct device * dev, char * buf, size_t count, loff_t off) { return off ? 0 : sprintf(buf,"%s\n",dev->name); @@ -166,7 +97,6 @@ }; struct driver_file_entry * device_default_files[] = { - &device_status_entry, &device_name_entry, &device_power_entry, NULL, diff -Nru a/drivers/base/power.c b/drivers/base/power.c --- a/drivers/base/power.c Sun Jun 2 18:44:56 2002 +++ b/drivers/base/power.c Sun Jun 2 18:44:56 2002 @@ -113,7 +113,7 @@ put_device(prev); if (dev->driver && dev->driver->remove) - dev->driver->remove(dev,REMOVE_FREE_RESOURCES); + dev->driver->remove(dev); spin_lock(&device_lock); prev = dev; diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c --- a/drivers/block/acsi.c Sun Jun 2 18:44:57 2002 +++ b/drivers/block/acsi.c Sun Jun 2 18:44:57 2002 @@ -1041,7 +1041,7 @@ } CurrentBuffer = buffer; CurrentNSect = nsect; - + if (CURRENT->cmd == WRITE) { CMDSET_TARG_LUN( write_cmd, target, lun ); CMDSET_BLOCK( write_cmd, block ); @@ -1049,7 +1049,7 @@ if (buffer == acsi_buffer) copy_to_acsibuffer(); dma_cache_maintenance( pbuffer, nsect*512, 1 ); - SET_INTR(write_intr); + DEVICE_INTR = write_intr; if (!acsicmd_dma( write_cmd, buffer, nsect, 1, 1)) { CLEAR_INTR; printk( KERN_ERR "ACSI (write): Timeout in command block\n" ); @@ -1063,7 +1063,7 @@ CMDSET_TARG_LUN( read_cmd, target, lun ); CMDSET_BLOCK( read_cmd, block ); CMDSET_LEN( read_cmd, nsect ); - SET_INTR(read_intr); + DEVICE_INTR = read_intr; if (!acsicmd_dma( read_cmd, buffer, nsect, 0, 1)) { CLEAR_INTR; printk( KERN_ERR "ACSI (read): Timeout in command block\n" ); diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c --- a/drivers/block/cpqarray.c Sun Jun 2 18:44:56 2002 +++ b/drivers/block/cpqarray.c Sun Jun 2 18:44:56 2002 @@ -1485,9 +1485,10 @@ int ctlr, i; unsigned long flags; - ctlr = major(dev) - MAJOR_NR; if (minor(dev) != 0) return -ENXIO; + + ctlr = major(dev) - MAJOR_NR; spin_lock_irqsave(IDA_LOCK(ctlr), flags); if (hba[ctlr]->usage_count > 1) { diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c --- a/drivers/block/floppy.c Sun Jun 2 18:44:56 2002 +++ b/drivers/block/floppy.c Sun Jun 2 18:44:56 2002 @@ -633,6 +633,8 @@ } #endif +static void (*do_floppy)(void) = NULL; + #ifdef FLOPPY_SANITY_CHECK #define OLOGSIZE 20 @@ -920,9 +922,9 @@ if (!fdc_busy) DPRINT("FDC access conflict!\n"); - if (DEVICE_INTR) + if (do_floppy) DPRINT("device interrupt still active at FDC release: %p!\n", - DEVICE_INTR); + do_floppy); command_status = FD_COMMAND_NONE; del_timer(&fd_timeout); cont = NULL; @@ -1005,7 +1007,7 @@ static void cancel_activity(void) { - CLEAR_INTR; + do_floppy = NULL; floppy_tq.routine = (void *)(void *) empty; del_timer(&fd_timer); } @@ -1524,7 +1526,7 @@ setup_DMA(); if (flags & FD_RAW_INTR) - SET_INTR(main_command_interrupt); + do_floppy = main_command_interrupt; r=0; for (i=0; i< raw_cmd->cmd_count; i++) @@ -1656,7 +1658,7 @@ } } - SET_INTR(seek_interrupt); + do_floppy = seek_interrupt; output_byte(FD_SEEK); output_byte(UNIT(current_drive)); LAST_OUT(track); @@ -1736,7 +1738,7 @@ /* interrupt handler. Note that this can be called externally on the Sparc */ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs) { - void (*handler)(void) = DEVICE_INTR; + void (*handler)(void) = do_floppy; int do_print; unsigned long f; @@ -1746,9 +1748,9 @@ f=claim_dma_lock(); fd_disable_dma(); release_dma_lock(f); - + floppy_enable_hlt(); - CLEAR_INTR; + do_floppy = NULL; if (fdc >= N_FDC || FDCS->address == -1){ /* we don't even know which FDC is the culprit */ printk("DOR0=%x\n", fdc_state[0].dor); @@ -1795,7 +1797,7 @@ #ifdef DEBUGT debugt("recalibrate floppy:"); #endif - SET_INTR(recal_interrupt); + do_floppy = recal_interrupt; output_byte(FD_RECALIBRATE); LAST_OUT(UNIT(current_drive)); } @@ -1823,14 +1825,14 @@ static void reset_fdc(void) { unsigned long flags; - - SET_INTR(reset_interrupt); + + do_floppy = reset_interrupt; FDCS->reset = 0; reset_fdc_info(0); /* Pseudo-DMA may intercept 'reset finished' interrupt. */ /* Irrelevant for systems with true DMA (i386). */ - + flags=claim_dma_lock(); fd_disable_dma(); release_dma_lock(flags); @@ -1873,8 +1875,8 @@ printk("status=%x\n", fd_inb(FD_STATUS)); printk("fdc_busy=%lu\n", fdc_busy); - if (DEVICE_INTR) - printk("DEVICE_INTR=%p\n", DEVICE_INTR); + if (do_floppy) + printk("do_floppy=%p\n", do_floppy); if (floppy_tq.sync) printk("floppy_tq.routine=%p\n", floppy_tq.routine); if (timer_pending(&fd_timer)) @@ -2920,7 +2922,7 @@ for (;;) { if (blk_queue_empty(QUEUE)) { - CLEAR_INTR; + do_floppy = NULL; unlock_fdc(); return; } diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Sun Jun 2 18:44:56 2002 +++ b/drivers/block/ll_rw_blk.c Sun Jun 2 18:44:56 2002 @@ -336,8 +336,10 @@ struct blk_queue_tag *tags; int bits, i; - if (depth > queue_nr_requests) + if (depth > queue_nr_requests) { depth = queue_nr_requests; + printk("blk_queue_init_tags: adjusted depth to %d\n", depth); + } tags = kmalloc(sizeof(struct blk_queue_tag),GFP_ATOMIC); if (!tags) @@ -362,7 +364,7 @@ * set the upper bits if the depth isn't a multiple of the word size */ for (i = depth; i < bits * BLK_TAGS_PER_LONG; i++) - set_bit(i, tags->tag_map); + __set_bit(i, tags->tag_map); /* * assign it, all done @@ -478,23 +480,39 @@ void blk_queue_invalidate_tags(request_queue_t *q) { struct blk_queue_tag *bqt = q->queue_tags; - struct list_head *tmp; + struct list_head *tmp, *n; struct request *rq; - list_for_each(tmp, &bqt->busy_list) { + list_for_each_safe(tmp, n, &bqt->busy_list) { rq = list_entry_rq(tmp); - blk_queue_end_tag(q, rq); + if (rq->tag == -1) { + printk("bad tag found on list\n"); + list_del(&rq->queuelist); + rq->flags &= ~REQ_QUEUED; + } else + blk_queue_end_tag(q, rq); + rq->flags &= ~REQ_STARTED; elv_add_request(q, rq, 0); } } -static char *rq_flags[] = { "REQ_RW", "REQ_RW_AHEAD", "REQ_BARRIER", - "REQ_CMD", "REQ_NOMERGE", "REQ_STARTED", - "REQ_DONTPREP", "REQ_QUEUED", "REQ_DRIVE_CMD", - "REQ_DRIVE_ACB", "REQ_PC", "REQ_BLOCK_PC", - "REQ_SENSE", "REQ_SPECIAL" }; +static char *rq_flags[] = { + "REQ_RW", + "REQ_RW_AHEAD", + "REQ_BARRIER", + "REQ_CMD", + "REQ_NOMERGE", + "REQ_STARTED", + "REQ_DONTPREP", + "REQ_QUEUED", + "REQ_DRIVE_ACB", + "REQ_PC", + "REQ_BLOCK_PC", + "REQ_SENSE", + "REQ_SPECIAL" +}; void blk_dump_rq_flags(struct request *rq, char *msg) { @@ -838,9 +856,15 @@ spin_unlock_irqrestore(q->queue_lock, flags); } -/* - * clear stop flag and run queue - */ +/** + * blk_start_queue - restart a previously stopped queue + * @q: The &request_queue_t in question + * + * Description: + * blk_start_queue() will clear the stop flag on the queue, and call + * the request_fn for the queue if it was in a stopped state when + * entered. Also see blk_stop_queue() + **/ void blk_start_queue(request_queue_t *q) { if (test_and_clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)) { @@ -853,17 +877,33 @@ } } -/* - * set stop bit, queue won't be run until blk_start_queue() is called - */ +/** + * blk_stop_queue - stop a queue + * @q: The &request_queue_t in question + * + * Description: + * The Linux block layer assumes that a block driver will consume all + * entries on the request queue when the request_fn strategy is called. + * Often this will not happen, because of hardware limitations (queue + * depth settings). If a device driver gets a 'queue full' response, + * or if it simply chooses not to queue more I/O at one point, it can + * call this function to prevent the request_fn from being called until + * the driver has signalled it's ready to go again. This happens by calling + * blk_start_queue() to restart queue operations. + **/ void blk_stop_queue(request_queue_t *q) { set_bit(QUEUE_FLAG_STOPPED, &q->queue_flags); } -/* - * the equivalent of the previous tq_disk run - */ +/** + * blk_run_queues - fire all plugged queues + * + * Description: + * Start I/O on all plugged queues known to the block layer. Queues that + * are currently stopped are ignored. This is equivalent to the older + * tq_disk task queue run. + **/ void blk_run_queues(void) { struct list_head *n, *tmp, local_plug_list; @@ -1924,9 +1964,11 @@ * Free request slots per queue. * (Half for reads, half for writes) */ - queue_nr_requests = 64; - if (total_ram > MB(32)) - queue_nr_requests = 256; + queue_nr_requests = (total_ram >> 8) & ~15; /* One per quarter-megabyte */ + if (queue_nr_requests < 32) + queue_nr_requests = 32; + if (queue_nr_requests > 512) + queue_nr_requests = 512; /* * Batch frees according to queue length diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c --- a/drivers/block/nbd.c Sun Jun 2 18:44:56 2002 +++ b/drivers/block/nbd.c Sun Jun 2 18:44:56 2002 @@ -24,6 +24,8 @@ * 01-3-11 Make nbd work with new Linux block layer code. It now supports * plugging like all the other block devices. Also added in MSG_MORE to * reduce number of partial TCP segments sent. + * 01-12-6 Fix deadlock condition by making queue locks independant of + * the transmit lock. * * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall * why not: would need verify_area and friends, would share yet another @@ -148,27 +150,28 @@ #define FAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)\n", result ); goto error_out; } -void nbd_send_req(struct socket *sock, struct request *req) +void nbd_send_req(struct nbd_device *lo, struct request *req) { - int result, rw, i, flags; + int result, i, flags; struct nbd_request request; unsigned long size = req->nr_sectors << 9; + struct socket *sock = lo->sock; DEBUG("NBD: sending control, "); - rw = rq_data_dir(req); - request.magic = htonl(NBD_REQUEST_MAGIC); - request.type = htonl((rw & WRITE) ? 1 : 0); + request.type = htonl(nbd_cmd(req)); request.from = cpu_to_be64( (u64) req->sector << 9); request.len = htonl(size); memcpy(request.handle, &req, sizeof(req)); - result = nbd_xmit(1, sock, (char *) &request, sizeof(request), rw & WRITE ? MSG_MORE : 0); + down(&lo->tx_lock); + + result = nbd_xmit(1, sock, (char *) &request, sizeof(request), nbd_cmd(req) == NBD_CMD_WRITE ? MSG_MORE : 0); if (result <= 0) FAIL("Sendmsg failed for control."); - if (rw & WRITE) { + if (nbd_cmd(req) == NBD_CMD_WRITE) { struct bio *bio; /* * we are really probing at internals to determine @@ -187,37 +190,59 @@ } } } + up(&lo->tx_lock); return; error_out: + up(&lo->tx_lock); req->errors++; } +static struct request *nbd_find_request(struct nbd_device *lo, char *handle) +{ + struct request *req; + struct list_head *tmp; + struct request *xreq; + + memcpy(&xreq, handle, sizeof(xreq)); + + spin_lock(&lo->queue_lock); + list_for_each(tmp, &lo->queue_head) { + req = list_entry(tmp, struct request, queuelist); + if (req != xreq) + continue; + list_del(&req->queuelist); + spin_unlock(&lo->queue_lock); + return req; + } + spin_unlock(&lo->queue_lock); + return NULL; +} + #define HARDFAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)\n", result ); lo->harderror = result; return NULL; } struct request *nbd_read_stat(struct nbd_device *lo) /* NULL returned = something went wrong, inform userspace */ { int result; struct nbd_reply reply; - struct request *xreq, *req; + struct request *req; DEBUG("reading control, "); reply.magic = 0; result = nbd_xmit(0, lo->sock, (char *) &reply, sizeof(reply), MSG_WAITALL); if (result <= 0) HARDFAIL("Recv control failed."); - memcpy(&xreq, reply.handle, sizeof(xreq)); - req = blkdev_entry_to_request(lo->queue_head.prev); - - if (xreq != req) - FAIL("Unexpected handle received.\n"); + req = nbd_find_request(lo, reply.handle); + if (req == NULL) + HARDFAIL("Unexpected reply"); DEBUG("ok, "); if (ntohl(reply.magic) != NBD_REPLY_MAGIC) HARDFAIL("Not enough magic."); if (ntohl(reply.error)) FAIL("Other side returned error."); - if (rq_data_dir(req) == READ) { + + if (nbd_cmd(req) == NBD_CMD_READ) { struct bio *bio = req->bio; DEBUG("data, "); do { @@ -240,20 +265,14 @@ { struct request *req; - down (&lo->tx_lock); while (1) { - up (&lo->tx_lock); req = nbd_read_stat(lo); - down (&lo->tx_lock); if (!req) { printk(KERN_ALERT "req should never be null\n" ); goto out; } #ifdef PARANOIA - if (req != blkdev_entry_to_request(lo->queue_head.prev)) { - printk(KERN_ALERT "NBD: I have problem...\n"); - } if (lo != &nbd_dev[minor(req->rq_dev)]) { printk(KERN_ALERT "NBD: request corrupted!\n"); continue; @@ -263,15 +282,10 @@ goto out; } #endif - blkdev_dequeue_request(req); - up (&lo->tx_lock); - nbd_end_request(req); - down (&lo->tx_lock); } out: - up (&lo->tx_lock); } void nbd_clear_que(struct nbd_device *lo) @@ -285,26 +299,19 @@ } #endif - while (!list_empty(&lo->queue_head)) { - req = blkdev_entry_to_request(lo->queue_head.prev); -#ifdef PARANOIA - if (!req) { - printk( KERN_ALERT "NBD: panic, panic, panic\n" ); - break; + do { + req = NULL; + spin_lock(&lo->queue_lock); + if (!list_empty(&lo->queue_head)) { + req = list_entry(lo->queue_head.next, struct request, queuelist); + list_del(&req->queuelist); } - if (lo != &nbd_dev[minor(req->rq_dev)]) { - printk(KERN_ALERT "NBD: request corrupted when clearing!\n"); - continue; + spin_unlock(&lo->queue_lock); + if (req) { + req->errors++; + nbd_end_request(req); } -#endif - req->errors++; - blkdev_dequeue_request(req); - up(&lo->tx_lock); - - nbd_end_request(req); - - down(&lo->tx_lock); - } + } while(req); } /* @@ -340,8 +347,12 @@ lo = &nbd_dev[dev]; if (!lo->file) FAIL("Request when not-ready."); - if ((rq_data_dir(req) == WRITE) && (lo->flags & NBD_READ_ONLY)) - FAIL("Write on read-only"); + nbd_cmd(req) = NBD_CMD_READ; + if (rq_data_dir(req) == WRITE) { + nbd_cmd(req) = NBD_CMD_WRITE; + if (lo->flags & NBD_READ_ONLY) + FAIL("Write on read-only"); + } #ifdef PARANOIA if (lo->magic != LO_MAGIC) FAIL("nbd[] is not magical!"); @@ -351,10 +362,11 @@ blkdev_dequeue_request(req); spin_unlock_irq(q->queue_lock); - down (&lo->tx_lock); + spin_lock(&lo->queue_lock); list_add(&req->queuelist, &lo->queue_head); - nbd_send_req(lo->sock, req); /* Why does this block? */ - up (&lo->tx_lock); + spin_unlock(&lo->queue_lock); + + nbd_send_req(lo, req); spin_lock_irq(q->queue_lock); continue; @@ -389,21 +401,23 @@ lo = &nbd_dev[dev]; switch (cmd) { case NBD_DISCONNECT: - printk("NBD_DISCONNECT\n") ; - sreq.flags = REQ_SPECIAL; /* FIXME: interpet as shutdown cmd */ - if (!lo->sock) return -EINVAL ; - nbd_send_req(lo->sock,&sreq) ; + printk(KERN_INFO "NBD_DISCONNECT\n"); + sreq.flags = REQ_SPECIAL; + nbd_cmd(&sreq) = NBD_CMD_DISC; + if (!lo->sock) + return -EINVAL; + nbd_send_req(lo, &sreq); return 0 ; case NBD_CLEAR_SOCK: - down(&lo->tx_lock); nbd_clear_que(lo); + spin_lock(&lo->queue_lock); if (!list_empty(&lo->queue_head)) { - up(&lo->tx_lock); + spin_unlock(&lo->queue_lock); printk(KERN_ERR "nbd: Some requests are in progress -> can not turn off.\n"); return -EBUSY; } - up(&lo->tx_lock); + spin_unlock(&lo->queue_lock); file = lo->file; if (!file) return -EINVAL; @@ -525,6 +539,7 @@ nbd_dev[i].file = NULL; nbd_dev[i].magic = LO_MAGIC; nbd_dev[i].flags = 0; + spin_lock_init(&nbd_dev[i].queue_lock); INIT_LIST_HEAD(&nbd_dev[i].queue_head); init_MUTEX(&nbd_dev[i].tx_lock); nbd_blksizes[i] = 1024; diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c --- a/drivers/block/ps2esdi.c Sun Jun 2 18:44:56 2002 +++ b/drivers/block/ps2esdi.c Sun Jun 2 18:44:56 2002 @@ -69,7 +69,7 @@ int ps2esdi_init(void); -static void ps2esdi_geninit(void); +static int ps2esdi_geninit(void); static void do_ps2esdi_request(request_queue_t * q); @@ -168,6 +168,8 @@ int __init ps2esdi_init(void) { + int error = 0; + /* register the device - pass the name, major number and operations vector . */ if (devfs_register_blkdev(MAJOR_NR, "ed", &ps2esdi_fops)) { @@ -180,7 +182,16 @@ /* some minor housekeeping - setup the global gendisk structure */ add_gendisk(&ps2esdi_gendisk); - ps2esdi_geninit(); + error = ps2esdi_geninit(); + if (error) { + printk(KERN_WARNING "PS2ESDI: error initialising" + " device, releasing resources\n"); + devfs_unregister_blkdev(MAJOR_NR, "ed"); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + del_gendisk(&ps2esdi_gendisk); + blk_clear(MAJOR_NR); + return error; + } return 0; } /* ps2esdi_init */ @@ -225,7 +236,7 @@ } release_region(io_base, 4); free_dma(dma_arb_level); - free_irq(PS2ESDI_IRQ, NULL); + free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); devfs_unregister_blkdev(MAJOR_NR, "ed"); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); del_gendisk(&ps2esdi_gendisk); @@ -289,7 +300,7 @@ } /* ps2 esdi specific initialization - called thru the gendisk chain */ -static void __init ps2esdi_geninit(void) +static int __init ps2esdi_geninit(void) { /* The first part contains the initialization code @@ -307,6 +318,7 @@ int slot = 0, i, reset_start, reset_end; u_char status; unsigned short adapterID; + int error = 0; if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) { adapterID = INTG_ESDI_ID; @@ -321,7 +333,7 @@ DEVICE_NAME, slot+1); mca_set_adapter_name(slot, "PS/2 ESDI"); } else { - return; + return -ENODEV; } ps2esdi_slot = slot; @@ -347,7 +359,8 @@ /* is it enabled ? */ if (!(status & STATUS_ENABLED)) { printk("%s: ESDI adapter disabled\n", DEVICE_NAME); - return; + error = -ENODEV; + goto err_out1; } /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can share with the SCSI driver */ @@ -357,7 +370,8 @@ SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk) ) { printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ); - return; + error = -EBUSY; + goto err_out1; } if (status & STATUS_ALTERNATE) io_base = ALT_IO_BASE; @@ -366,8 +380,8 @@ if (!request_region(io_base, 4, "ed")) { printk(KERN_WARNING"Unable to request region 0x%x\n", io_base); - free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); - return; + error = -EBUSY; + goto err_out2; } /* get the dma arbitration level */ dma_arb_level = (status >> 2) & 0xf; @@ -417,8 +431,12 @@ ps2esdi_gendisk.nr_real = ps2esdi_drives; - request_dma(dma_arb_level, "ed"); - + if (request_dma(dma_arb_level, "ed") !=0) { + printk(KERN_WARNING "PS2ESDI: Can't request dma-channel %d\n" + ,(int) dma_arb_level); + error = -EBUSY; + goto err_out3; + } blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 128); for (i = 0; i < ps2esdi_drives; i++) { @@ -428,6 +446,18 @@ ps2esdi_info[i].cyl); ps2esdi_valid[i] = 1; } + return 0; + +err_out3: + release_region(io_base, 4); +err_out2: + free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); +err_out1: + if(ps2esdi_slot) { + mca_mark_as_unused(ps2esdi_slot); + mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); + } + return error; } static void __init ps2esdi_get_device_cfg(void) diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c --- a/drivers/block/xd.c Sun Jun 2 18:44:57 2002 +++ b/drivers/block/xd.c Sun Jun 2 18:44:57 2002 @@ -107,6 +107,8 @@ { 0x0010,"ST11 BIOS v1.7",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11R" }, /* Alan Hourihane, alanh@fairlite.demon.co.uk */ { 0x1000,"(c)Copyright 1987 SMS",xd_omti_init_controller,xd_omti_init_drive,"n OMTI 5520" }, /* Dirk Melchers, dirk@merlin.nbg.sub.org */ { 0x0006,"COPYRIGHT XEBEC (C) 1984",xd_xebec_init_controller,xd_xebec_init_drive," XEBEC" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */ + { 0x0008,"(C) Copyright 1984 Western Digital Corp", xd_wd_init_controller, xd_wd_init_drive," Western Dig. 1002s-wx2" }, + { 0x0008,"(C) Copyright 1986 Western Digital Corporation", xd_wd_init_controller, xd_wd_init_drive," 1986 Western Digital" }, /* jfree@sovereign.org */ }; static unsigned int xd_bases[] __initdata = diff -Nru a/drivers/cdrom/Config.help b/drivers/cdrom/Config.help --- a/drivers/cdrom/Config.help Sun Jun 2 18:44:57 2002 +++ b/drivers/cdrom/Config.help Sun Jun 2 18:44:57 2002 @@ -106,27 +106,6 @@ The module will be called sbpcd.o. If you want to compile it as a module, say M here and read . -CONFIG_SBPCD2 - Say Y here only if you have two CD-ROM controller cards of this type - (usually only if you have more than four drives). You should enter - the parameters for the second, third and fourth interface card into - before compiling the new kernel. Read - the file . - -CONFIG_SBPCD3 - Say Y here only if you have three CD-ROM controller cards of this - type (usually only if you have more than six drives). You should - enter the parameters for the second, third and fourth interface card - into before compiling the new kernel. - Read the file . - -CONFIG_SBPCD4 - Say Y here only if you have four CD-ROM controller cards of this - type (usually only if you have more than eight drives). You should - enter the parameters for the second, third and fourth interface card - into before compiling the new kernel. - Read the file . - CONFIG_AZTCD This is your driver if you have an Aztech CDA268-01A, Orchid CD-3110, Okano or Wearnes CDD110, Conrad TXC, or CyCD-ROM CR520 or diff -Nru a/drivers/cdrom/Config.in b/drivers/cdrom/Config.in --- a/drivers/cdrom/Config.in Sun Jun 2 18:44:56 2002 +++ b/drivers/cdrom/Config.in Sun Jun 2 18:44:56 2002 @@ -4,15 +4,6 @@ tristate ' Aztech/Orchid/Okano/Wearnes/TXC/CyDROM CDROM support' CONFIG_AZTCD tristate ' Goldstar R420 CDROM support' CONFIG_GSCD tristate ' Matsushita/Panasonic/Creative, Longshine, TEAC CDROM support' CONFIG_SBPCD -if [ "$CONFIG_SBPCD" = "y" ]; then - bool ' Matsushita/Panasonic, ... second CDROM controller support' CONFIG_SBPCD2 - if [ "$CONFIG_SBPCD2" = "y" ]; then - bool ' Matsushita/Panasonic, ... third CDROM controller support' CONFIG_SBPCD3 - if [ "$CONFIG_SBPCD3" = "y" ]; then - bool ' Matsushita/Panasonic, ... fourth CDROM controller support' CONFIG_SBPCD4 - fi - fi -fi tristate ' Mitsumi (standard) [no XA/Multisession] CDROM support' CONFIG_MCD if [ "$CONFIG_MCD" != "n" ]; then int 'MCD IRQ' CONFIG_MCD_IRQ 11 diff -Nru a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile --- a/drivers/cdrom/Makefile Sun Jun 2 18:44:57 2002 +++ b/drivers/cdrom/Makefile Sun Jun 2 18:44:57 2002 @@ -34,9 +34,6 @@ obj-$(CONFIG_MCDX) += mcdx.o cdrom.o obj-$(CONFIG_OPTCD) += optcd.o obj-$(CONFIG_SBPCD) += sbpcd.o cdrom.o -obj-$(CONFIG_SBPCD2) += sbpcd2.o cdrom.o -obj-$(CONFIG_SBPCD3) += sbpcd3.o cdrom.o -obj-$(CONFIG_SBPCD4) += sbpcd4.o cdrom.o obj-$(CONFIG_SJCD) += sjcd.o obj-$(CONFIG_CDU535) += sonycd535.o diff -Nru a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c --- a/drivers/cdrom/aztcd.c Sun Jun 2 18:44:58 2002 +++ b/drivers/cdrom/aztcd.c Sun Jun 2 18:44:58 2002 @@ -1724,16 +1724,18 @@ long int count, max_count; unsigned char result[50]; int st; + void* status = NULL; int i = 0; + int ret = 0; if (azt_port == 0) { - printk("aztcd: no Aztech CD-ROM Initialization"); + printk(KERN_INFO "aztcd: no Aztech CD-ROM Initialization"); return -EIO; } - printk - ("aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM CD-ROM Driver\n"); - printk("aztcd: (C) 1994-98 W.Zimmermann\n"); + printk(KERN_INFO "aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM " + "CD-ROM Driver\n"); + printk(KERN_INFO "aztcd: (C) 1994-98 W.Zimmermann\n"); if (azt_port == -1) { printk ("aztcd: KernelVersion=%s DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n", @@ -1742,8 +1744,8 @@ printk ("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n", AZT_VERSION, azt_port); - printk - ("aztcd: If you have problems, read /usr/src/linux/Documentation/cdrom/aztcd\n"); + printk(KERN_INFO "aztcd: If you have problems, read /usr/src/linux/" + "Documentation/cdrom/aztcd\n"); #ifdef AZT_SW32 /*CDROM connected to Soundwave32 card */ @@ -1764,15 +1766,15 @@ /* check for presence of drive */ - if (azt_port == -1) { /* autoprobing */ + if (azt_port == -1) { /* autoprobing for proprietary interface */ for (i = 0; (azt_port_auto[i] != 0) && (i < 16); i++) { azt_port = azt_port_auto[i]; - printk("aztcd: Autoprobing BaseAddress=0x%x \n", - azt_port); - st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes */ - if (st) + printk(KERN_INFO "aztcd: Autoprobing BaseAddress=0x%x" + "\n", azt_port); + /*proprietary interfaces need 4 bytes */ + if (!request_region(azt_port, 4, "aztcd")) { continue; - + } outb(POLLED, MODE_PORT); inb(CMD_PORT); inb(CMD_PORT); @@ -1785,22 +1787,25 @@ if (aztTimeOutCount >= AZT_FAST_TIMEOUT) break; } while (aztIndatum & AFL_STATUS); - if (inb(DATA_PORT) == AFL_OP_OK) + if (inb(DATA_PORT) == AFL_OP_OK) { /* OK drive found */ break; + } + else { /* Drive not found on this port - try next one */ + release_region(azt_port, 4); + } } if ((azt_port_auto[i] == 0) || (i == 16)) { - printk("aztcd: no AZTECH CD-ROM drive found\n"); + printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n"); return -EIO; } } else { /* no autoprobing */ if ((azt_port == 0x1f0) || (azt_port == 0x170)) - st = check_region(azt_port, 8); /*IDE-interfaces need 8 bytes */ + status = request_region(azt_port, 8, "aztcd"); /*IDE-interfaces need 8 bytes */ else - st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes */ - if (st) { - printk - ("aztcd: conflict, I/O port (%X) already used\n", - azt_port); + status = request_region(azt_port, 4, "aztcd"); /*proprietary interfaces need 4 bytes */ + if (!status) { + printk(KERN_WARNING "aztcd: conflict, I/O port (%X) " + "already used\n", azt_port); return -EIO; } @@ -1823,17 +1828,19 @@ if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? If not, reset and try again */ #ifndef MODULE if (azt_cont != 0x79) { - printk - ("aztcd: no AZTECH CD-ROM drive found-Try boot parameter aztcd=,0x79\n"); - return -EIO; + printk(KERN_WARNING "aztcd: no AZTECH CD-ROM " + "drive found-Try boot parameter aztcd=" + ",0x79\n"); + ret = -EIO; + goto err_out; } #else if (0) { } #endif else { - printk - ("aztcd: drive reset - please wait\n"); + printk(KERN_INFO "aztcd: drive reset - " + "please wait\n"); for (count = 0; count < 50; count++) { inb(STATUS_PORT); /*removing all data from earlier tries */ inb(DATA_PORT); @@ -1845,9 +1852,10 @@ outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */ STEN_LOW; if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */ - printk - ("aztcd: no AZTECH CD-ROM drive found\n"); - return -EIO; + printk(KERN_WARNING "aztcd: no AZTECH " + "CD-ROM drive found\n"); + ret = -EIO; + goto err_out; } for (count = 0; count < AZT_TIMEOUT; @@ -1855,13 +1863,13 @@ barrier(); /* Stop gcc 2.96 being smart */ if ((st = getAztStatus()) == -1) { - printk - ("aztcd: Drive Status Error Status=%x\n", - st); - return -EIO; + printk(KERN_WARNING "aztcd: Drive Status" + " Error Status=%x\n", st); + ret = -EIO; + goto err_out; } #ifdef AZT_DEBUG - printk("aztcd: Status = %x\n", st); + printk(KERN_DEBUG "aztcd: Status = %x\n", st); #endif outb(POLLED, MODE_PORT); inb(CMD_PORT); @@ -1916,29 +1924,34 @@ printk("%c", result[count]); printk("<<>> "); printk("Aborted\n"); - return -EIO; + ret = -EIO; + goto err_out; } } devfs_register(NULL, "aztcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUGO | S_IWUGO, &azt_fops, NULL); if (devfs_register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) { - printk("aztcd: Unable to get major %d for Aztech CD-ROM\n", - MAJOR_NR); - return -EIO; + printk(KERN_WARNING "aztcd: Unable to get major %d for Aztech" + " CD-ROM\n", MAJOR_NR); + ret = -EIO; + goto err_out; } blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_aztcd_request, &aztSpin); blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048); register_disk(NULL, mk_kdev(MAJOR_NR, 0), 1, &azt_fops, 0); - if ((azt_port == 0x1f0) || (azt_port == 0x170)) - request_region(azt_port, 8, "aztcd"); /*IDE-interface */ - else - request_region(azt_port, 4, "aztcd"); /*proprietary interface */ - azt_invalidate_buffers(); aztPresent = 1; aztCloseDoor(); return (0); + err_out: + if ((azt_port == 0x1f0) || (azt_port == 0x170)) { + SWITCH_IDE_MASTER; + release_region(azt_port, 8); /*IDE-interface */ + } else + release_region(azt_port, 4); /*proprietary interface */ + return ret; + } void __exit aztcd_exit(void) diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c --- a/drivers/cdrom/gscd.c Sun Jun 2 18:44:56 2002 +++ b/drivers/cdrom/gscd.c Sun Jun 2 18:44:56 2002 @@ -292,7 +292,7 @@ goto out; if (CURRENT->cmd != READ) { - printk("GSCD: bad cmd %d\n", CURRENT->cmd); + printk("GSCD: bad cmd %p\n", CURRENT->cmd); end_request(0); goto repeat; } @@ -941,7 +941,7 @@ return; } blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - release_region(gscd_port, 4); + release_region(gscd_port, GSCD_IO_EXTENT); printk(KERN_INFO "GoldStar-module released.\n"); } @@ -964,16 +964,16 @@ { int i; int result; + int ret=0; printk(KERN_INFO "GSCD: version %s\n", GSCD_VERSION); printk(KERN_INFO "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n", gscd_port); - if (check_region(gscd_port, 4)) { - printk - ("GSCD: Init failed, I/O port (%X) already in use.\n", - gscd_port); + if (!request_region(gscd_port, GSCD_IO_EXTENT, "gscd")) { + printk(KERN_WARNING "GSCD: Init failed, I/O port (%X) already" + " in use.\n", gscd_port); return -EIO; } @@ -981,24 +981,27 @@ /* check for card */ result = wait_drv_ready(); if (result == 0x09) { - printk("GSCD: DMA kann ich noch nicht!\n"); - return -EIO; + printk(KERN_WARNING "GSCD: DMA kann ich noch nicht!\n"); + ret = -EIO; + goto err_out1; } if (result == 0x0b) { drv_mode = result; i = find_drives(); if (i == 0) { - printk - ("GSCD: GoldStar CD-ROM Drive is not found.\n"); - return -EIO; + printk(KERN_WARNING "GSCD: GoldStar CD-ROM Drive is" + " not found.\n"); + ret = -EIO; + goto err_out1; } } if ((result != 0x0b) && (result != 0x09)) { - printk - ("GSCD: GoldStar Interface Adapter does not exist or H/W error\n"); - return -EIO; + printk(KERN_WARNING "GSCD: GoldStar Interface Adapter does not " + "exist or H/W error\n"); + ret = -EIO; + goto err_out1; } /* reset all drives */ @@ -1012,10 +1015,10 @@ } if (devfs_register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) { - printk - ("GSCD: Unable to get major %d for GoldStar CD-ROM\n", - MAJOR_NR); - return -EIO; + printk(KERN_WARNING "GSCD: Unable to get major %d for GoldStar " + "CD-ROM\n", MAJOR_NR); + ret = -EIO; + goto err_out1; } devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL); @@ -1025,11 +1028,13 @@ disk_state = 0; gscdPresent = 1; - request_region(gscd_port, 4, "gscd"); register_disk(NULL, mk_kdev(MAJOR_NR, 0), 1, &gscd_fops, 0); printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n"); return 0; +err_out1: + release_region(gscd_port, GSCD_IO_EXTENT); + return ret; } static void gscd_hsg2msf(long hsg, struct msf *msf) diff -Nru a/drivers/cdrom/gscd.h b/drivers/cdrom/gscd.h --- a/drivers/cdrom/gscd.h Sun Jun 2 18:44:56 2002 +++ b/drivers/cdrom/gscd.h Sun Jun 2 18:44:56 2002 @@ -15,11 +15,10 @@ Appropriate settings are: 0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360 0x370, 0x380, 0x390, 0x3A0, 0x3B0, 0x3C0, 0x3D0, 0x3E0, 0x3F0 */ -/* insert here the I/O port address */ +/* insert here the I/O port address and extent */ #define GSCD_BASE_ADDR 0x340 +#define GSCD_IO_EXTENT 4 -/* change this to set the dma-channel */ -#define GSCD_DMA_CHANNEL 3 /* not used */ /************** nothing to set up below here *********************/ diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c --- a/drivers/cdrom/sbpcd.c Sun Jun 2 18:44:56 2002 +++ b/drivers/cdrom/sbpcd.c Sun Jun 2 18:44:56 2002 @@ -1,5 +1,3 @@ - - /* * sbpcd.c CD-ROM device driver for the whole family of traditional, * non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives. @@ -341,16 +339,20 @@ /* * Trying to merge requests breaks this driver horribly (as in it goes - * boom and apparently has done so since 2.3.41). As it is a legacy - * driver for a horribly slow double speed CD on a hideous interface - * designed for polled operation, I won't loose any sleep in simply + * boom and apparently has done so since 2.3.41). As it is a legacy + * driver for a horribly slow double speed CD on a hideous interface + * designed for polled operation, I won't loose any sleep in simply * disallowing merging. Paul G. 02/2001 + * + * Thu May 30 14:14:47 CEST 2002: + * + * I have presumably found the reson for the above - there was a bogous + * end_request substitute, which was manipulating the request queues + * incorrectly. If someone has access to the actual hardware, and it's + * still operations - well please free to test it. + * + * Marcin Dalecki */ -#define DONT_MERGE_REQUESTS - -#ifndef SBPCD_ISSUE -#define SBPCD_ISSUE 1 -#endif /* SBPCD_ISSUE */ #include @@ -364,7 +366,7 @@ #include #include #include -#include +#include #include #include #include @@ -377,50 +379,19 @@ #include #include "sbpcd.h" -#if !(SBPCD_ISSUE-1) #define MAJOR_NR MATSUSHITA_CDROM_MAJOR -#endif -#if !(SBPCD_ISSUE-2) -#define MAJOR_NR MATSUSHITA_CDROM2_MAJOR /* second driver issue */ -#endif -#if !(SBPCD_ISSUE-3) -#define MAJOR_NR MATSUSHITA_CDROM3_MAJOR /* third driver issue */ -#endif -#if !(SBPCD_ISSUE-4) -#define MAJOR_NR MATSUSHITA_CDROM4_MAJOR /* fourth driver issue */ -#endif #include /*==========================================================================*/ -/* - * provisions for more than 1 driver issues - * currently up to 4 drivers, expandable - */ -#if !(SBPCD_ISSUE-1) -#define DO_SBPCD_REQUEST(a) do_sbpcd_request(a) -#define SBPCD_INIT(a) sbpcd_init(a) -#endif -#if !(SBPCD_ISSUE-2) -#define DO_SBPCD_REQUEST(a) do_sbpcd2_request(a) -#define SBPCD_INIT(a) sbpcd2_init(a) -#endif -#if !(SBPCD_ISSUE-3) -#define DO_SBPCD_REQUEST(a) do_sbpcd3_request(a) -#define SBPCD_INIT(a) sbpcd3_init(a) -#endif -#if !(SBPCD_ISSUE-4) -#define DO_SBPCD_REQUEST(a) do_sbpcd4_request(a) -#define SBPCD_INIT(a) sbpcd4_init(a) -#endif -/*==========================================================================*/ #if SBPCD_DIS_IRQ -#define SBPCD_CLI cli() -#define SBPCD_STI sti() +# define SBPCD_CLI cli() +# define SBPCD_STI sti() #else -#define SBPCD_CLI -#define SBPCD_STI -#endif /* SBPCD_DIS_IRQ */ +# define SBPCD_CLI +# define SBPCD_STI +#endif + /*==========================================================================*/ /* * auto-probing address list @@ -438,8 +409,7 @@ * send mail to emoenke@gwdg.de if your interface card is not FULLY * represented here. */ -#if !(SBPCD_ISSUE-1) -static int sbpcd[] = +static int sbpcd[] = { CDROM_PORT, SBPRO, /* probe with user's setup first */ #if DISTRIBUTION @@ -482,31 +452,18 @@ #endif #endif /* DISTRIBUTION */ }; -#else -static int sbpcd[] = {CDROM_PORT, SBPRO}; /* probe with user's setup only */ -#endif + +/* + * Protects access to global structures etc. + */ +static spinlock_t sbpcd_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; + MODULE_PARM(sbpcd, "2i"); MODULE_PARM(max_drives, "i"); #define NUM_PROBE (sizeof(sbpcd) / sizeof(int)) /*==========================================================================*/ -/* - * the external references: - */ -#if !(SBPCD_ISSUE-1) -#ifdef CONFIG_SBPCD2 -extern int sbpcd2_init(void); -#endif -#ifdef CONFIG_SBPCD3 -extern int sbpcd3_init(void); -#endif -#ifdef CONFIG_SBPCD4 -extern int sbpcd4_init(void); -#endif -#endif - -/*==========================================================================*/ #define INLINE inline @@ -604,19 +561,7 @@ static const char *str_sp = "SPEA"; static const char *str_t16 = "Teac16bit"; static const char *type; - -#if !(SBPCD_ISSUE-1) static const char *major_name="sbpcd"; -#endif -#if !(SBPCD_ISSUE-2) -static const char *major_name="sbpcd2"; -#endif -#if !(SBPCD_ISSUE-3) -static const char *major_name="sbpcd3"; -#endif -#if !(SBPCD_ISSUE-4) -static const char *major_name="sbpcd4"; -#endif /*==========================================================================*/ @@ -4879,15 +4824,12 @@ * */ #undef DEBUG_GTL -static inline void sbpcd_end_request(struct request *req, int uptodate) { - list_add(&req->queue, &req->q->queue_head); - end_request(uptodate); -} + /*==========================================================================*/ /* * I/O request routine, called from Linux kernel. */ -static void DO_SBPCD_REQUEST(request_queue_t * q) +static void do_sbpcd_request(request_queue_t * q) { u_int block; u_int nsect; @@ -4921,11 +4863,11 @@ return; } - req=CURRENT; /* take out our request so no other */ + req = CURRENT; /* take out our request so no other */ blkdev_dequeue_request(req); /* task can fuck it up GTL */ if (req -> sector == -1) - sbpcd_end_request(req, 0); + end_request(0); spin_unlock_irq(q->queue_lock); down(&ioctl_read_sem); @@ -4967,7 +4909,7 @@ #endif up(&ioctl_read_sem); spin_lock_irq(q->queue_lock); - sbpcd_end_request(req, 1); + end_request(1); goto request_loop; } @@ -5008,7 +4950,7 @@ #endif up(&ioctl_read_sem); spin_lock_irq(q->queue_lock); - sbpcd_end_request(req, 1); + end_request(1); goto request_loop; } } @@ -5024,7 +4966,7 @@ up(&ioctl_read_sem); sbp_sleep(0); /* wait a bit, try again */ spin_lock_irq(q->queue_lock); - sbpcd_end_request(req, 0); + end_request(0); goto request_loop; } /*==========================================================================*/ @@ -5469,7 +5411,7 @@ static void sbpcd_release(struct cdrom_device_info * cdi) { int i; - + i = minor(cdi->dev); if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) { @@ -5488,7 +5430,6 @@ if (--D_S[d].open_count<=0) { D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1; - invalidate_buffers(cdi->dev); if (D_S[d].audio_state!=audio_playing) if (D_S[d].f_eject) cc_SpinDown(); D_S[d].diskstate_flags &= ~cd_size_bit; @@ -5559,11 +5500,7 @@ * */ -#if (SBPCD_ISSUE-1) -static int sbpcd_setup(char *s) -#else int sbpcd_setup(char *s) -#endif { #ifndef MODULE int p[4]; @@ -5680,20 +5617,6 @@ return (0); } -#ifdef DONT_MERGE_REQUESTS -static int dont_merge_requests_fn(request_queue_t *q, struct request *req, - struct request *next, int max_segments) -{ - return 0; -} - -static int dont_bh_merge_fn(request_queue_t *q, struct request *req, - struct buffer_head *bh, int max_segments) -{ - return 0; -} -#endif - /*==========================================================================*/ /* * Test for presence of drive and initialize it. @@ -5703,10 +5626,10 @@ static devfs_handle_t devfs_handle; #ifdef MODULE -int __init __SBPCD_INIT(void) +int __init __sbpcd_init(void) #else -int __init SBPCD_INIT(void) -#endif /* MODULE */ +int __init sbpcd_init(void) +#endif { char nbuff[16]; int i=0, j=0; @@ -5841,7 +5764,7 @@ i=SetSpeed(); if (i>=0) D_S[j].CD_changed=1; } - + /* * Turn on the CD audio channels. * The addresses are obtained from SOUND_BASE (see sbpcd.h). @@ -5849,8 +5772,8 @@ #if SOUND_BASE OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */ OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */ -#endif /* SOUND_BASE */ - +#endif /* SOUND_BASE */ + if (devfs_register_blkdev(MAJOR_NR, major_name, &sbpcd_bdops) != 0) { msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR); @@ -5860,16 +5783,10 @@ goto init_done; #endif /* MODULE */ } - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DO_SBPCD_REQUEST, &sbpcd_lock); -#ifdef DONT_MERGE_REQUESTS - (BLK_DEFAULT_QUEUE(MAJOR_NR))->back_merge_fn = dont_bh_merge_fn; - (BLK_DEFAULT_QUEUE(MAJOR_NR))->front_merge_fn = dont_bh_merge_fn; - (BLK_DEFAULT_QUEUE(MAJOR_NR))->merge_requests_fn = dont_merge_requests_fn; -#endif - read_ahead[MAJOR_NR] = buffers * (CD_FRAMESIZE / 512); - + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_sbpcd_request, &sbpcd_lock); + request_region(CDo_command,4,major_name); - + devfs_handle = devfs_mk_dir (NULL, "sbp", NULL); for (j=0;jdev = MKDEV(MAJOR_NR, j); + sbpcd_infop->dev = mk_kdev(MAJOR_NR, j); strncpy(sbpcd_infop->name,major_name, sizeof(sbpcd_infop->name)); - sprintf (nbuff, "c%dt%d/cd", SBPCD_ISSUE - 1, D_S[j].drv_id); + sprintf (nbuff, "c0t%d/cd", D_S[j].drv_id); sbpcd_infop->de = devfs_register (devfs_handle, nbuff, DEVFS_FL_DEFAULT, MAJOR_NR, j, S_IFBLK | S_IRUGO | S_IWUGO, &sbpcd_bdops, NULL); if (register_cdrom(sbpcd_infop)) { - printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n"); + printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n"); } } blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), CD_FRAMESIZE); #ifndef MODULE init_done: -#if !(SBPCD_ISSUE-1) -#ifdef CONFIG_SBPCD2 - sbpcd2_init(); -#endif /* CONFIG_SBPCD2 */ -#ifdef CONFIG_SBPCD3 - sbpcd3_init(); -#endif /* CONFIG_SBPCD3 */ -#ifdef CONFIG_SBPCD4 - sbpcd4_init(); -#endif /* CONFIG_SBPCD4 */ -#endif /* !(SBPCD_ISSUE-1) */ -#endif /* MODULE */ +#endif return 0; } /*==========================================================================*/ @@ -5978,14 +5884,11 @@ msg(DBG_INF, "%s module released.\n", major_name); } - -#ifdef MODULE -module_init(__SBPCD_INIT) /*HACK!*/; -#endif +module_init(__sbpcd_init) /*HACK!*/; module_exit(sbpcd_exit); -#endif /* MODULE */ +#endif /* MODULE */ /*==========================================================================*/ /* * Check if the media has changed in the CD-ROM drive. @@ -6003,7 +5906,7 @@ D_S[i].CD_changed=0; msg(DBG_CHK,"medium changed (drive %d)\n", i); /* BUG! Should invalidate buffers! --AJK */ - invalidate_buffers(full_dev); + /* Why should it do the above at all?! --mdcki */ D_S[d].diskstate_flags &= ~toc_bit; D_S[d].diskstate_flags &= ~cd_size_bit; #if SAFE_MIXED diff -Nru a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h --- a/drivers/cdrom/sbpcd.h Sun Jun 2 18:44:56 2002 +++ b/drivers/cdrom/sbpcd.h Sun Jun 2 18:44:56 2002 @@ -74,30 +74,10 @@ * Example: #define SOUND_BASE 0x220 enables the sound card's CD channels * #define SOUND_BASE 0 leaves the soundcard untouched */ -#if !(SBPCD_ISSUE-1) /* first (or if you have only one) interface board: */ #define CDROM_PORT 0x340 /* <-----------<< port address */ #define SBPRO 0 /* <-----------<< interface type */ #define MAX_DRIVES 4 /* set to 1 if the card does not use "drive select" */ #define SOUND_BASE 0x220 /* <-----------<< sound address of this card or 0 */ -#endif -#if !(SBPCD_ISSUE-2) /* ==================== second interface board: === */ -#define CDROM_PORT 0x344 /* <-----------<< port address */ -#define SBPRO 0 /* <-----------<< interface type */ -#define MAX_DRIVES 4 /* set to 1 if the card does not use "drive select" */ -#define SOUND_BASE 0x000 /* <-----------<< sound address of this card or 0 */ -#endif -#if !(SBPCD_ISSUE-3) /* ===================== third interface board: === */ -#define CDROM_PORT 0x630 /* <-----------<< port address */ -#define SBPRO 1 /* <-----------<< interface type */ -#define MAX_DRIVES 4 /* set to 1 if the card does not use "drive select" */ -#define SOUND_BASE 0x240 /* <-----------<< sound address of this card or 0 */ -#endif -#if !(SBPCD_ISSUE-4) /* ==================== fourth interface board: === */ -#define CDROM_PORT 0x634 /* <-----------<< port address */ -#define SBPRO 0 /* <-----------<< interface type */ -#define MAX_DRIVES 4 /* set to 1 if the card does not use "drive select" */ -#define SOUND_BASE 0x000 /* <-----------<< sound address of this card or 0 */ -#endif /* * some more or less user dependent definitions - service them! diff -Nru a/drivers/cdrom/sbpcd2.c b/drivers/cdrom/sbpcd2.c --- a/drivers/cdrom/sbpcd2.c Sun Jun 2 18:44:58 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,5 +0,0 @@ -/* - * duplication of sbpcd.c for multiple interfaces - */ -#define SBPCD_ISSUE 2 -#include "sbpcd.c" diff -Nru a/drivers/cdrom/sbpcd3.c b/drivers/cdrom/sbpcd3.c --- a/drivers/cdrom/sbpcd3.c Sun Jun 2 18:44:58 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,5 +0,0 @@ -/* - * duplication of sbpcd.c for multiple interfaces - */ -#define SBPCD_ISSUE 3 -#include "sbpcd.c" diff -Nru a/drivers/cdrom/sbpcd4.c b/drivers/cdrom/sbpcd4.c --- a/drivers/cdrom/sbpcd4.c Sun Jun 2 18:44:56 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,5 +0,0 @@ -/* - * duplication of sbpcd.c for multiple interfaces - */ -#define SBPCD_ISSUE 4 -#include "sbpcd.c" diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c --- a/drivers/cdrom/sonycd535.c Sun Jun 2 18:44:57 2002 +++ b/drivers/cdrom/sonycd535.c Sun Jun 2 18:44:57 2002 @@ -118,6 +118,7 @@ #include #include #include +#include #include #include #include @@ -134,7 +135,8 @@ #include #define MAJOR_NR CDU535_CDROM_MAJOR -# include +#include + #define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */ #include "sonycd535.h" @@ -1589,7 +1591,6 @@ &cdu_fops, NULL); if (devfs_register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) { printk("Unable to get major %d for %s\n", - devfs_unregister(sony_devfs_handle); MAJOR_NR, CDU535_MESSAGE_NAME); return -EIO; } @@ -1663,8 +1664,7 @@ devfs_unregister(sony_devfs_handle); if (sony535_irq_used) free_irq(sony535_irq_used, NULL); - } - + return -EIO; } register_disk(NULL, mk_kdev(MAJOR_NR,0), 1, &cdu_fops, 0); diff -Nru a/drivers/char/Config.help b/drivers/char/Config.help --- a/drivers/char/Config.help Sun Jun 2 18:44:57 2002 +++ b/drivers/char/Config.help Sun Jun 2 18:44:57 2002 @@ -127,6 +127,10 @@ 815 and 830m chipset boards for their on-board integrated graphics. This is required to do any useful video modes with these boards. +CONFIG_AGP_I460 + This option gives you AGP GART support for the Intel 460GX chipset + for IA64 processors. + CONFIG_AGP_VIA This option gives you AGP support for the GLX component of the XFree86 4.x on VIA MPV3/Apollo Pro chipsets. @@ -170,6 +174,10 @@ You should say Y here if you use XFree86 3.3.6 or 4.x and want to use GLX or DRI. If unsure, say N. +CONFIG_AGP_HP_ZX1 + This option gives you AGP GART support for the HP ZX1 chipset + for IA64 processors. + CONFIG_I810_TCO Hardware driver for the TCO timer built into the Intel i810 and i815 chipset family. The TCO (Total Cost of Ownership) timer is a @@ -1187,3 +1195,7 @@ Not sure? It's safe to say N. +CONFIG_HVC_CONSOLE + pSeries machines when partitioned support a hypervisor virtual + console. This driver allows each pSeries partition to have a console + which is accessed via the HMC. diff -Nru a/drivers/char/Config.in b/drivers/char/Config.in --- a/drivers/char/Config.in Sun Jun 2 18:44:56 2002 +++ b/drivers/char/Config.in Sun Jun 2 18:44:56 2002 @@ -105,6 +105,9 @@ fi dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT fi +if [ "$CONFIG_PPC_PSERIES" = "y" ]; then + bool 'pSeries Hypervisor Virtual Console support' CONFIG_HVC_CONSOLE +fi source drivers/i2c/Config.in @@ -217,6 +220,7 @@ bool ' ALI chipset support' CONFIG_AGP_ALI bool ' Serverworks LE/HE support' CONFIG_AGP_SWORKS if [ "$CONFIG_IA64" = "y" ]; then + bool ' Intel 460GX support' CONFIG_AGP_I460 bool ' HP ZX1 AGP support' CONFIG_AGP_HP_ZX1 fi fi diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile --- a/drivers/char/Makefile Sun Jun 2 18:44:57 2002 +++ b/drivers/char/Makefile Sun Jun 2 18:44:57 2002 @@ -155,6 +155,7 @@ obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o obj-$(CONFIG_SERIAL_TX3912) += generic_serial.o serial_tx3912.o +obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o obj-$(CONFIG_ATIXL_BUSMOUSE) += atixlmouse.o obj-$(CONFIG_LOGIBUSMOUSE) += logibusmouse.o diff -Nru a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h --- a/drivers/char/agp/agp.h Sun Jun 2 18:44:57 2002 +++ b/drivers/char/agp/agp.h Sun Jun 2 18:44:57 2002 @@ -172,6 +172,12 @@ #ifndef PCI_DEVICE_ID_INTEL_810_0 #define PCI_DEVICE_ID_INTEL_810_0 0x7120 #endif +#ifndef PCI_DEVICE_ID_INTEL_845_G_0 +#define PCI_DEVICE_ID_INTEL_845_G_0 0x2560 +#endif +#ifndef PCI_DEVICE_ID_INTEL_845_G_1 +#define PCI_DEVICE_ID_INTEL_845_G_1 0x2562 +#endif #ifndef PCI_DEVICE_ID_INTEL_830_M_0 #define PCI_DEVICE_ID_INTEL_830_M_0 0x3575 #endif @@ -223,6 +229,9 @@ #ifndef PCI_DEVICE_ID_INTEL_82443GX_1 #define PCI_DEVICE_ID_INTEL_82443GX_1 0x71a1 #endif +#ifndef PCI_DEVICE_ID_INTEL_460GX +#define PCI_DEVICE_ID_INTEL_460GX 0x84ea +#endif #ifndef PCI_DEVICE_ID_AMD_IRONGATE_0 #define PCI_DEVICE_ID_AMD_IRONGATE_0 0x7006 #endif @@ -267,6 +276,15 @@ #define INTEL_AGPCTRL 0xb0 #define INTEL_NBXCFG 0x50 #define INTEL_ERRSTS 0x91 + +/* Intel 460GX Registers */ +#define INTEL_I460_APBASE 0x10 +#define INTEL_I460_BAPBASE 0x98 +#define INTEL_I460_GXBCTL 0xa0 +#define INTEL_I460_AGPSIZ 0xa2 +#define INTEL_I460_ATTBASE 0xfe200000 +#define INTEL_I460_GATT_VALID (1UL << 24) +#define INTEL_I460_GATT_COHERENT (1UL << 25) /* intel i830 registers */ #define I830_GMCH_CTRL 0x52 diff -Nru a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c --- a/drivers/char/agp/agpgart_be.c Sun Jun 2 18:44:56 2002 +++ b/drivers/char/agp/agpgart_be.c Sun Jun 2 18:44:56 2002 @@ -1365,6 +1365,570 @@ #endif /* CONFIG_AGP_I810 */ +#ifdef CONFIG_AGP_I460 + +/* BIOS configures the chipset so that one of two apbase registers are used */ +static u8 intel_i460_dynamic_apbase = 0x10; + +/* 460 supports multiple GART page sizes, so GART pageshift is dynamic */ +static u8 intel_i460_pageshift = 12; +static u32 intel_i460_pagesize; + +/* Keep track of which is larger, chipset or kernel page size. */ +static u32 intel_i460_cpk = 1; + +/* Structure for tracking partial use of 4MB GART pages */ +static u32 **i460_pg_detail = NULL; +static u32 *i460_pg_count = NULL; + +#define I460_CPAGES_PER_KPAGE (PAGE_SIZE >> intel_i460_pageshift) +#define I460_KPAGES_PER_CPAGE ((1 << intel_i460_pageshift) >> PAGE_SHIFT) + +#define I460_SRAM_IO_DISABLE (1 << 4) +#define I460_BAPBASE_ENABLE (1 << 3) +#define I460_AGPSIZ_MASK 0x7 +#define I460_4M_PS (1 << 1) + +#define log2(x) ffz(~(x)) + +static inline void intel_i460_read_back (volatile u32 *entry) +{ + /* + * The 460 spec says we have to read the last location written to + * make sure that all writes have taken effect + */ + *entry; +} + +static int intel_i460_fetch_size(void) +{ + int i; + u8 temp; + aper_size_info_8 *values; + + /* Determine the GART page size */ + pci_read_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL, &temp); + intel_i460_pageshift = (temp & I460_4M_PS) ? 22 : 12; + intel_i460_pagesize = 1UL << intel_i460_pageshift; + + values = A_SIZE_8(agp_bridge.aperture_sizes); + + pci_read_config_byte(agp_bridge.dev, INTEL_I460_AGPSIZ, &temp); + + /* Exit now if the IO drivers for the GART SRAMS are turned off */ + if (temp & I460_SRAM_IO_DISABLE) { + printk(KERN_ERR PFX "GART SRAMS disabled on 460GX chipset\n"); + printk(KERN_ERR PFX "AGPGART operation not possible\n"); + return 0; + } + + /* Make sure we don't try to create an 2 ^ 23 entry GATT */ + if ((intel_i460_pageshift == 0) && ((temp & I460_AGPSIZ_MASK) == 4)) { + printk(KERN_ERR PFX "We can't have a 32GB aperture with 4KB GART pages\n"); + return 0; + } + + /* Determine the proper APBASE register */ + if (temp & I460_BAPBASE_ENABLE) + intel_i460_dynamic_apbase = INTEL_I460_BAPBASE; + else + intel_i460_dynamic_apbase = INTEL_I460_APBASE; + + for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { + /* + * Dynamically calculate the proper num_entries and page_order values for + * the define aperture sizes. Take care not to shift off the end of + * values[i].size. + */ + values[i].num_entries = (values[i].size << 8) >> (intel_i460_pageshift - 12); + values[i].page_order = log2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT); + } + + for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { + /* Neglect control bits when matching up size_value */ + if ((temp & I460_AGPSIZ_MASK) == values[i].size_value) { + agp_bridge.previous_size = agp_bridge.current_size = (void *) (values + i); + agp_bridge.aperture_size_idx = i; + return values[i].size; + } + } + + return 0; +} + +/* There isn't anything to do here since 460 has no GART TLB. */ +static void intel_i460_tlb_flush(agp_memory * mem) +{ + return; +} + +/* + * This utility function is needed to prevent corruption of the control bits + * which are stored along with the aperture size in 460's AGPSIZ register + */ +static void intel_i460_write_agpsiz(u8 size_value) +{ + u8 temp; + + pci_read_config_byte(agp_bridge.dev, INTEL_I460_AGPSIZ, &temp); + pci_write_config_byte(agp_bridge.dev, INTEL_I460_AGPSIZ, + ((temp & ~I460_AGPSIZ_MASK) | size_value)); +} + +static void intel_i460_cleanup(void) +{ + aper_size_info_8 *previous_size; + + previous_size = A_SIZE_8(agp_bridge.previous_size); + intel_i460_write_agpsiz(previous_size->size_value); + + if (intel_i460_cpk == 0) { + vfree(i460_pg_detail); + vfree(i460_pg_count); + } +} + + +/* Control bits for Out-Of-GART coherency and Burst Write Combining */ +#define I460_GXBCTL_OOG (1UL << 0) +#define I460_GXBCTL_BWC (1UL << 2) + +static int intel_i460_configure(void) +{ + union { + u32 small[2]; + u64 large; + } temp; + u8 scratch; + int i; + + aper_size_info_8 *current_size; + + temp.large = 0; + + current_size = A_SIZE_8(agp_bridge.current_size); + intel_i460_write_agpsiz(current_size->size_value); + + /* + * Do the necessary rigmarole to read all eight bytes of APBASE. + * This has to be done since the AGP aperture can be above 4GB on + * 460 based systems. + */ + pci_read_config_dword(agp_bridge.dev, intel_i460_dynamic_apbase, &(temp.small[0])); + pci_read_config_dword(agp_bridge.dev, intel_i460_dynamic_apbase + 4, &(temp.small[1])); + + /* Clear BAR control bits */ + agp_bridge.gart_bus_addr = temp.large & ~((1UL << 3) - 1); + + pci_read_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL, &scratch); + pci_write_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL, + (scratch & 0x02) | I460_GXBCTL_OOG | I460_GXBCTL_BWC); + + /* + * Initialize partial allocation trackers if a GART page is bigger than + * a kernel page. + */ + if (I460_CPAGES_PER_KPAGE >= 1) { + intel_i460_cpk = 1; + } else { + intel_i460_cpk = 0; + + i460_pg_detail = vmalloc(sizeof(*i460_pg_detail) * current_size->num_entries); + i460_pg_count = vmalloc(sizeof(*i460_pg_count) * current_size->num_entries); + + for (i = 0; i < current_size->num_entries; i++) { + i460_pg_count[i] = 0; + i460_pg_detail[i] = NULL; + } + } + return 0; +} + +static int intel_i460_create_gatt_table(void) +{ + char *table; + int i; + int page_order; + int num_entries; + void *temp; + + /* + * Load up the fixed address of the GART SRAMS which hold our + * GATT table. + */ + table = (char *) __va(INTEL_I460_ATTBASE); + + temp = agp_bridge.current_size; + page_order = A_SIZE_8(temp)->page_order; + num_entries = A_SIZE_8(temp)->num_entries; + + agp_bridge.gatt_table_real = (u32 *) table; + agp_bridge.gatt_table = ioremap_nocache(virt_to_phys(table), + (PAGE_SIZE * (1 << page_order))); + agp_bridge.gatt_bus_addr = virt_to_phys(agp_bridge.gatt_table_real); + + for (i = 0; i < num_entries; i++) { + agp_bridge.gatt_table[i] = 0; + } + + intel_i460_read_back(agp_bridge.gatt_table + i - 1); + return 0; +} + +static int intel_i460_free_gatt_table(void) +{ + int num_entries; + int i; + void *temp; + + temp = agp_bridge.current_size; + + num_entries = A_SIZE_8(temp)->num_entries; + + for (i = 0; i < num_entries; i++) { + agp_bridge.gatt_table[i] = 0; + } + + intel_i460_read_back(agp_bridge.gatt_table + i - 1); + + iounmap(agp_bridge.gatt_table); + return 0; +} + +/* These functions are called when PAGE_SIZE exceeds the GART page size */ + +static int intel_i460_insert_memory_cpk(agp_memory * mem, off_t pg_start, int type) +{ + int i, j, k, num_entries; + void *temp; + unsigned long paddr; + + /* + * The rest of the kernel will compute page offsets in terms of + * PAGE_SIZE. + */ + pg_start = I460_CPAGES_PER_KPAGE * pg_start; + + temp = agp_bridge.current_size; + num_entries = A_SIZE_8(temp)->num_entries; + + if ((pg_start + I460_CPAGES_PER_KPAGE * mem->page_count) > num_entries) { + printk(KERN_ERR PFX "Looks like we're out of AGP memory\n"); + return -EINVAL; + } + + j = pg_start; + while (j < (pg_start + I460_CPAGES_PER_KPAGE * mem->page_count)) { + if (!PGE_EMPTY(agp_bridge.gatt_table[j])) { + return -EBUSY; + } + j++; + } + +#if 0 + /* not necessary since 460 GART is operated in coherent mode... */ + if (mem->is_flushed == FALSE) { + CACHE_FLUSH(); + mem->is_flushed = TRUE; + } +#endif + + for (i = 0, j = pg_start; i < mem->page_count; i++) { + paddr = mem->memory[i]; + for (k = 0; k < I460_CPAGES_PER_KPAGE; k++, j++, paddr += intel_i460_pagesize) + agp_bridge.gatt_table[j] = (u32) agp_bridge.mask_memory(paddr, mem->type); + } + + intel_i460_read_back(agp_bridge.gatt_table + j - 1); + return 0; +} + +static int intel_i460_remove_memory_cpk(agp_memory * mem, off_t pg_start, int type) +{ + int i; + + pg_start = I460_CPAGES_PER_KPAGE * pg_start; + + for (i = pg_start; i < (pg_start + I460_CPAGES_PER_KPAGE * mem->page_count); i++) + agp_bridge.gatt_table[i] = 0; + + intel_i460_read_back(agp_bridge.gatt_table + i - 1); + return 0; +} + +/* + * These functions are called when the GART page size exceeds PAGE_SIZE. + * + * This situation is interesting since AGP memory allocations that are + * smaller than a single GART page are possible. The structures i460_pg_count + * and i460_pg_detail track partial allocation of the large GART pages to + * work around this issue. + * + * i460_pg_count[pg_num] tracks the number of kernel pages in use within + * GART page pg_num. i460_pg_detail[pg_num] is an array containing a + * psuedo-GART entry for each of the aforementioned kernel pages. The whole + * of i460_pg_detail is equivalent to a giant GATT with page size equal to + * that of the kernel. + */ + +static void *intel_i460_alloc_large_page(int pg_num) +{ + int i; + void *bp, *bp_end; + struct page *page; + + i460_pg_detail[pg_num] = (void *) vmalloc(sizeof(u32) * I460_KPAGES_PER_CPAGE); + if (i460_pg_detail[pg_num] == NULL) { + printk(KERN_ERR PFX "Out of memory, we're in trouble...\n"); + return NULL; + } + + for (i = 0; i < I460_KPAGES_PER_CPAGE; i++) + i460_pg_detail[pg_num][i] = 0; + + bp = (void *) __get_free_pages(GFP_KERNEL, intel_i460_pageshift - PAGE_SHIFT); + if (bp == NULL) { + printk(KERN_ERR PFX "Couldn't alloc 4M GART page...\n"); + return NULL; + } + + bp_end = bp + ((PAGE_SIZE * (1 << (intel_i460_pageshift - PAGE_SHIFT))) - 1); + + for (page = virt_to_page(bp); page <= virt_to_page(bp_end); page++) { + atomic_inc(&agp_bridge.current_memory_agp); + } + return bp; +} + +static void intel_i460_free_large_page(int pg_num, unsigned long addr) +{ + struct page *page; + void *bp, *bp_end; + + bp = (void *) __va(addr); + bp_end = bp + (PAGE_SIZE * (1 << (intel_i460_pageshift - PAGE_SHIFT))); + + vfree(i460_pg_detail[pg_num]); + i460_pg_detail[pg_num] = NULL; + + for (page = virt_to_page(bp); page < virt_to_page(bp_end); page++) { + atomic_dec(&agp_bridge.current_memory_agp); + } + + free_pages((unsigned long) bp, intel_i460_pageshift - PAGE_SHIFT); +} + +static int intel_i460_insert_memory_kpc(agp_memory * mem, off_t pg_start, int type) +{ + int i, pg, start_pg, end_pg, start_offset, end_offset, idx; + int num_entries; + void *temp; + unsigned long paddr; + + temp = agp_bridge.current_size; + num_entries = A_SIZE_8(temp)->num_entries; + + /* Figure out what pg_start means in terms of our large GART pages */ + start_pg = pg_start / I460_KPAGES_PER_CPAGE; + start_offset = pg_start % I460_KPAGES_PER_CPAGE; + end_pg = (pg_start + mem->page_count - 1) / I460_KPAGES_PER_CPAGE; + end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_CPAGE; + + if (end_pg > num_entries) { + printk(KERN_ERR PFX "Looks like we're out of AGP memory\n"); + return -EINVAL; + } + + /* Check if the requested region of the aperture is free */ + for (pg = start_pg; pg <= end_pg; pg++) { + /* Allocate new GART pages if necessary */ + if (i460_pg_detail[pg] == NULL) { + temp = intel_i460_alloc_large_page(pg); + if (temp == NULL) + return -ENOMEM; + agp_bridge.gatt_table[pg] = agp_bridge.mask_memory((unsigned long) temp, + 0); + intel_i460_read_back(agp_bridge.gatt_table + pg); + } + + for (idx = ((pg == start_pg) ? start_offset : 0); + idx < ((pg == end_pg) ? (end_offset + 1) : I460_KPAGES_PER_CPAGE); + idx++) + { + if (i460_pg_detail[pg][idx] != 0) + return -EBUSY; + } + } + +#if 0 + /* not necessary since 460 GART is operated in coherent mode... */ + if (mem->is_flushed == FALSE) { + CACHE_FLUSH(); + mem->is_flushed = TRUE; + } +#endif + + for (pg = start_pg, i = 0; pg <= end_pg; pg++) { + paddr = agp_bridge.unmask_memory(agp_bridge.gatt_table[pg]); + for (idx = ((pg == start_pg) ? start_offset : 0); + idx < ((pg == end_pg) ? (end_offset + 1) : I460_KPAGES_PER_CPAGE); + idx++, i++) + { + mem->memory[i] = paddr + (idx * PAGE_SIZE); + i460_pg_detail[pg][idx] = agp_bridge.mask_memory(mem->memory[i], + mem->type); + i460_pg_count[pg]++; + } + } + + return 0; +} + +static int intel_i460_remove_memory_kpc(agp_memory * mem, off_t pg_start, int type) +{ + int i, pg, start_pg, end_pg, start_offset, end_offset, idx; + int num_entries; + void *temp; + unsigned long paddr; + + temp = agp_bridge.current_size; + num_entries = A_SIZE_8(temp)->num_entries; + + /* Figure out what pg_start means in terms of our large GART pages */ + start_pg = pg_start / I460_KPAGES_PER_CPAGE; + start_offset = pg_start % I460_KPAGES_PER_CPAGE; + end_pg = (pg_start + mem->page_count - 1) / I460_KPAGES_PER_CPAGE; + end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_CPAGE; + + for (i = 0, pg = start_pg; pg <= end_pg; pg++) { + for (idx = ((pg == start_pg) ? start_offset : 0); + idx < ((pg == end_pg) ? (end_offset + 1) : I460_KPAGES_PER_CPAGE); + idx++, i++) + { + mem->memory[i] = 0; + i460_pg_detail[pg][idx] = 0; + i460_pg_count[pg]--; + } + + /* Free GART pages if they are unused */ + if (i460_pg_count[pg] == 0) { + paddr = agp_bridge.unmask_memory(agp_bridge.gatt_table[pg]); + agp_bridge.gatt_table[pg] = agp_bridge.scratch_page; + intel_i460_read_back(agp_bridge.gatt_table + pg); + intel_i460_free_large_page(pg, paddr); + } + } + return 0; +} + +/* Dummy routines to call the approriate {cpk,kpc} function */ + +static int intel_i460_insert_memory(agp_memory * mem, off_t pg_start, int type) +{ + if (intel_i460_cpk) + return intel_i460_insert_memory_cpk(mem, pg_start, type); + else + return intel_i460_insert_memory_kpc(mem, pg_start, type); +} + +static int intel_i460_remove_memory(agp_memory * mem, off_t pg_start, int type) +{ + if (intel_i460_cpk) + return intel_i460_remove_memory_cpk(mem, pg_start, type); + else + return intel_i460_remove_memory_kpc(mem, pg_start, type); +} + +/* + * If the kernel page size is smaller that the chipset page size, we don't + * want to allocate memory until we know where it is to be bound in the + * aperture (a multi-kernel-page alloc might fit inside of an already + * allocated GART page). Consequently, don't allocate or free anything + * if i460_cpk (meaning chipset pages per kernel page) isn't set. + * + * Let's just hope nobody counts on the allocated AGP memory being there + * before bind time (I don't think current drivers do)... + */ +static unsigned long intel_i460_alloc_page(void) +{ + if (intel_i460_cpk) + return agp_generic_alloc_page(); + + /* Returning NULL would cause problems */ + return ~0UL; +} + +static void intel_i460_destroy_page(unsigned long page) +{ + if (intel_i460_cpk) + agp_generic_destroy_page(page); +} + +static gatt_mask intel_i460_masks[] = +{ + { + INTEL_I460_GATT_VALID | INTEL_I460_GATT_COHERENT, + 0 + } +}; + +static unsigned long intel_i460_mask_memory(unsigned long addr, int type) +{ + /* Make sure the returned address is a valid GATT entry */ + return (agp_bridge.masks[0].mask + | (((addr & ~((1 << intel_i460_pageshift) - 1)) & 0xffffff000) >> 12)); +} + +static unsigned long intel_i460_unmask_memory(unsigned long addr) +{ + /* Turn a GATT entry into a physical address */ + return ((addr & 0xffffff) << 12); +} + +static aper_size_info_8 intel_i460_sizes[3] = +{ + /* + * The 32GB aperture is only available with a 4M GART page size. + * Due to the dynamic GART page size, we can't figure out page_order + * or num_entries until runtime. + */ + {32768, 0, 0, 4}, + {1024, 0, 0, 2}, + {256, 0, 0, 1} +}; + +static int __init intel_i460_setup (struct pci_dev *pdev __attribute__((unused))) +{ + agp_bridge.masks = intel_i460_masks; + agp_bridge.aperture_sizes = (void *) intel_i460_sizes; + agp_bridge.size_type = U8_APER_SIZE; + agp_bridge.num_aperture_sizes = 3; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = intel_i460_configure; + agp_bridge.fetch_size = intel_i460_fetch_size; + agp_bridge.cleanup = intel_i460_cleanup; + agp_bridge.tlb_flush = intel_i460_tlb_flush; + agp_bridge.mask_memory = intel_i460_mask_memory; + agp_bridge.unmask_memory = intel_i460_unmask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = intel_i460_create_gatt_table; + agp_bridge.free_gatt_table = intel_i460_free_gatt_table; + agp_bridge.insert_memory = intel_i460_insert_memory; + agp_bridge.remove_memory = intel_i460_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = intel_i460_alloc_page; + agp_bridge.agp_destroy_page = intel_i460_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 1; + return 0; +} + +#endif /* CONFIG_AGP_I460 */ + #ifdef CONFIG_AGP_INTEL static int intel_fetch_size(void) @@ -3273,368 +3837,6 @@ * AGP devices and collect their data. */ -#ifdef CONFIG_AGP_HP_ZX1 - -#ifndef log2 -#define log2(x) ffz(~(x)) -#endif - -#define HP_ZX1_IOVA_BASE GB(1UL) -#define HP_ZX1_IOVA_SIZE GB(1UL) -#define HP_ZX1_GART_SIZE (HP_ZX1_IOVA_SIZE / 2) -#define HP_ZX1_SBA_IOMMU_COOKIE 0x0000badbadc0ffeeUL - -#define HP_ZX1_PDIR_VALID_BIT 0x8000000000000000UL -#define HP_ZX1_IOVA_TO_PDIR(va) ((va - hp_private.iova_base) >> \ - hp_private.io_tlb_shift) - -static aper_size_info_fixed hp_zx1_sizes[] = -{ - {0, 0, 0}, /* filled in by hp_zx1_fetch_size() */ -}; - -static gatt_mask hp_zx1_masks[] = -{ - {HP_ZX1_PDIR_VALID_BIT, 0} -}; - -static struct _hp_private { - struct pci_dev *ioc; - volatile u8 *registers; - u64 *io_pdir; // PDIR for entire IOVA - u64 *gatt; // PDIR just for GART (subset of above) - u64 gatt_entries; - u64 iova_base; - u64 gart_base; - u64 gart_size; - u64 io_pdir_size; - int io_pdir_owner; // do we own it, or share it with sba_iommu? - int io_page_size; - int io_tlb_shift; - int io_tlb_ps; // IOC ps config - int io_pages_per_kpage; -} hp_private; - -static int __init hp_zx1_ioc_shared(void) -{ - struct _hp_private *hp = &hp_private; - - printk(KERN_INFO PFX "HP ZX1 IOC: IOPDIR shared with sba_iommu\n"); - - /* - * IOC already configured by sba_iommu module; just use - * its setup. We assume: - * - IOVA space is 1Gb in size - * - first 512Mb is IOMMU, second 512Mb is GART - */ - hp->io_tlb_ps = INREG64(hp->registers, HP_ZX1_TCNFG); - switch (hp->io_tlb_ps) { - case 0: hp->io_tlb_shift = 12; break; - case 1: hp->io_tlb_shift = 13; break; - case 2: hp->io_tlb_shift = 14; break; - case 3: hp->io_tlb_shift = 16; break; - default: - printk(KERN_ERR PFX "Invalid IOTLB page size " - "configuration 0x%x\n", hp->io_tlb_ps); - hp->gatt = 0; - hp->gatt_entries = 0; - return -ENODEV; - } - hp->io_page_size = 1 << hp->io_tlb_shift; - hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size; - - hp->iova_base = INREG64(hp->registers, HP_ZX1_IBASE) & ~0x1; - hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - HP_ZX1_GART_SIZE; - - hp->gart_size = HP_ZX1_GART_SIZE; - hp->gatt_entries = hp->gart_size / hp->io_page_size; - - hp->io_pdir = phys_to_virt(INREG64(hp->registers, HP_ZX1_PDIR_BASE)); - hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; - - if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) { - hp->gatt = 0; - hp->gatt_entries = 0; - printk(KERN_ERR PFX "No reserved IO PDIR entry found; " - "GART disabled\n"); - return -ENODEV; - } - - return 0; -} - -static int __init hp_zx1_ioc_owner(u8 ioc_rev) -{ - struct _hp_private *hp = &hp_private; - - printk(KERN_INFO PFX "HP ZX1 IOC: IOPDIR dedicated to GART\n"); - - /* - * Select an IOV page size no larger than system page size. - */ - if (PAGE_SIZE >= KB(64)) { - hp->io_tlb_shift = 16; - hp->io_tlb_ps = 3; - } else if (PAGE_SIZE >= KB(16)) { - hp->io_tlb_shift = 14; - hp->io_tlb_ps = 2; - } else if (PAGE_SIZE >= KB(8)) { - hp->io_tlb_shift = 13; - hp->io_tlb_ps = 1; - } else { - hp->io_tlb_shift = 12; - hp->io_tlb_ps = 0; - } - hp->io_page_size = 1 << hp->io_tlb_shift; - hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size; - - hp->iova_base = HP_ZX1_IOVA_BASE; - hp->gart_size = HP_ZX1_GART_SIZE; - hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - hp->gart_size; - - hp->gatt_entries = hp->gart_size / hp->io_page_size; - hp->io_pdir_size = (HP_ZX1_IOVA_SIZE / hp->io_page_size) * sizeof(u64); - - return 0; -} - -static int __init hp_zx1_ioc_init(void) -{ - struct _hp_private *hp = &hp_private; - struct pci_dev *ioc; - int i; - u8 ioc_rev; - - ioc = pci_find_device(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_ZX1_IOC, NULL); - if (!ioc) { - printk(KERN_ERR PFX "Detected HP ZX1 AGP bridge but no IOC\n"); - return -ENODEV; - } - hp->ioc = ioc; - - pci_read_config_byte(ioc, PCI_REVISION_ID, &ioc_rev); - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - if (pci_resource_flags(ioc, i) == IORESOURCE_MEM) { - hp->registers = (u8 *) ioremap(pci_resource_start(ioc, - i), - pci_resource_len(ioc, i)); - break; - } - } - if (!hp->registers) { - printk(KERN_ERR PFX "Detected HP ZX1 AGP bridge but no CSRs\n"); - - return -ENODEV; - } - - /* - * If the IOTLB is currently disabled, we can take it over. - * Otherwise, we have to share with sba_iommu. - */ - hp->io_pdir_owner = (INREG64(hp->registers, HP_ZX1_IBASE) & 0x1) == 0; - - if (hp->io_pdir_owner) - return hp_zx1_ioc_owner(ioc_rev); - - return hp_zx1_ioc_shared(); -} - -static int hp_zx1_fetch_size(void) -{ - int size; - - size = hp_private.gart_size / MB(1); - hp_zx1_sizes[0].size = size; - agp_bridge.current_size = (void *) &hp_zx1_sizes[0]; - return size; -} - -static int hp_zx1_configure(void) -{ - struct _hp_private *hp = &hp_private; - - agp_bridge.gart_bus_addr = hp->gart_base; - agp_bridge.capndx = pci_find_capability(agp_bridge.dev, PCI_CAP_ID_AGP); - pci_read_config_dword(agp_bridge.dev, - agp_bridge.capndx + PCI_AGP_STATUS, &agp_bridge.mode); - - if (hp->io_pdir_owner) { - OUTREG64(hp->registers, HP_ZX1_PDIR_BASE, - virt_to_phys(hp->io_pdir)); - OUTREG64(hp->registers, HP_ZX1_TCNFG, hp->io_tlb_ps); - OUTREG64(hp->registers, HP_ZX1_IMASK, ~(HP_ZX1_IOVA_SIZE - 1)); - OUTREG64(hp->registers, HP_ZX1_IBASE, hp->iova_base | 0x1); - OUTREG64(hp->registers, HP_ZX1_PCOM, - hp->iova_base | log2(HP_ZX1_IOVA_SIZE)); - INREG64(hp->registers, HP_ZX1_PCOM); - } - - return 0; -} - -static void hp_zx1_cleanup(void) -{ - struct _hp_private *hp = &hp_private; - - if (hp->io_pdir_owner) - OUTREG64(hp->registers, HP_ZX1_IBASE, 0); - iounmap((void *) hp->registers); -} - -static void hp_zx1_tlbflush(agp_memory * mem) -{ - struct _hp_private *hp = &hp_private; - - OUTREG64(hp->registers, HP_ZX1_PCOM, - hp->gart_base | log2(hp->gart_size)); - INREG64(hp->registers, HP_ZX1_PCOM); -} - -static int hp_zx1_create_gatt_table(void) -{ - struct _hp_private *hp = &hp_private; - int i; - - if (hp->io_pdir_owner) { - hp->io_pdir = (u64 *) __get_free_pages(GFP_KERNEL, - get_order(hp->io_pdir_size)); - if (!hp->io_pdir) { - printk(KERN_ERR PFX "Couldn't allocate contiguous " - "memory for I/O PDIR\n"); - hp->gatt = 0; - hp->gatt_entries = 0; - return -ENOMEM; - } - memset(hp->io_pdir, 0, hp->io_pdir_size); - - hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; - } - - for (i = 0; i < hp->gatt_entries; i++) { - hp->gatt[i] = (unsigned long) agp_bridge.scratch_page; - } - - return 0; -} - -static int hp_zx1_free_gatt_table(void) -{ - struct _hp_private *hp = &hp_private; - - if (hp->io_pdir_owner) - free_pages((unsigned long) hp->io_pdir, - get_order(hp->io_pdir_size)); - else - hp->gatt[0] = HP_ZX1_SBA_IOMMU_COOKIE; - return 0; -} - -static int hp_zx1_insert_memory(agp_memory * mem, off_t pg_start, int type) -{ - struct _hp_private *hp = &hp_private; - int i, k; - off_t j, io_pg_start; - int io_pg_count; - - if (type != 0 || mem->type != 0) { - return -EINVAL; - } - - io_pg_start = hp->io_pages_per_kpage * pg_start; - io_pg_count = hp->io_pages_per_kpage * mem->page_count; - if ((io_pg_start + io_pg_count) > hp->gatt_entries) { - return -EINVAL; - } - - j = io_pg_start; - while (j < (io_pg_start + io_pg_count)) { - if (hp->gatt[j]) { - return -EBUSY; - } - j++; - } - - if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); - mem->is_flushed = TRUE; - } - - for (i = 0, j = io_pg_start; i < mem->page_count; i++) { - unsigned long paddr; - - paddr = mem->memory[i]; - for (k = 0; - k < hp->io_pages_per_kpage; - k++, j++, paddr += hp->io_page_size) { - hp->gatt[j] = agp_bridge.mask_memory(paddr, type); - } - } - - agp_bridge.tlb_flush(mem); - return 0; -} - -static int hp_zx1_remove_memory(agp_memory * mem, off_t pg_start, int type) -{ - struct _hp_private *hp = &hp_private; - int i, io_pg_start, io_pg_count; - - if (type != 0 || mem->type != 0) { - return -EINVAL; - } - - io_pg_start = hp->io_pages_per_kpage * pg_start; - io_pg_count = hp->io_pages_per_kpage * mem->page_count; - for (i = io_pg_start; i < io_pg_count + io_pg_start; i++) { - hp->gatt[i] = agp_bridge.scratch_page; - } - - agp_bridge.tlb_flush(mem); - return 0; -} - -static unsigned long hp_zx1_mask_memory(unsigned long addr, int type) -{ - return HP_ZX1_PDIR_VALID_BIT | addr; -} - -static unsigned long hp_zx1_unmask_memory(unsigned long addr) -{ - return addr & ~(HP_ZX1_PDIR_VALID_BIT); -} - -static int __init hp_zx1_setup (struct pci_dev *pdev) -{ - agp_bridge.masks = hp_zx1_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.dev_private_data = NULL; - agp_bridge.size_type = FIXED_APER_SIZE; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = hp_zx1_configure; - agp_bridge.fetch_size = hp_zx1_fetch_size; - agp_bridge.cleanup = hp_zx1_cleanup; - agp_bridge.tlb_flush = hp_zx1_tlbflush; - agp_bridge.mask_memory = hp_zx1_mask_memory; - agp_bridge.unmask_memory = hp_zx1_unmask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = hp_zx1_create_gatt_table; - agp_bridge.free_gatt_table = hp_zx1_free_gatt_table; - agp_bridge.insert_memory = hp_zx1_insert_memory; - agp_bridge.remove_memory = hp_zx1_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.cant_use_aperture = 1; - - return hp_zx1_ioc_init(); - - (void) pdev; /* unused */ -} - -#endif /* CONFIG_AGP_HP_ZX1 */ pci_for_each_dev(device) { cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); @@ -4296,6 +4498,12 @@ "Intel", "i830M", intel_830mp_setup }, + { PCI_DEVICE_ID_INTEL_845_G_0, + PCI_VENDOR_ID_INTEL, + INTEL_I845_G, + "Intel", + "i845G", + intel_830mp_setup }, { PCI_DEVICE_ID_INTEL_840_0, PCI_VENDOR_ID_INTEL, INTEL_I840, @@ -4458,15 +4666,6 @@ hp_zx1_setup }, #endif -#ifdef CONFIG_AGP_HP_ZX1 - { PCI_DEVICE_ID_HP_ZX1_LBA, - PCI_VENDOR_ID_HP, - HP_ZX1, - "HP", - "ZX1", - hp_zx1_setup }, -#endif - { 0, }, /* dummy final entry, always present */ }; @@ -4620,16 +4819,38 @@ NULL); if (i810_dev == NULL) { printk(KERN_ERR PFX "agpgart: Detected an " - "Intel i815, but could not find the" - " secondary device. Assuming a " - "non-integrated video card.\n"); + "Intel i815, but could not find the" + " secondary device. Assuming a " + "non-integrated video card.\n"); break; } printk(KERN_INFO PFX "agpgart: Detected an Intel i815 " - "Chipset.\n"); + "Chipset.\n"); agp_bridge.type = INTEL_I810; return intel_i810_setup(i810_dev); + case PCI_DEVICE_ID_INTEL_845_G_0: + i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_845_G_1, NULL); + if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) { + i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_845_G_1, i810_dev); + } + + if (i810_dev == NULL) { + /* + * We probably have a I845MP chipset + * with an external graphics + * card. It will be initialized later + */ + agp_bridge.type = INTEL_I845_G; + break; + } + printk(KERN_INFO PFX "Detected an Intel " + "845G Chipset.\n"); + agp_bridge.type = INTEL_I810; + return intel_i830_setup(i810_dev); + case PCI_DEVICE_ID_INTEL_830_M_0: i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_830_M_1, @@ -4641,8 +4862,8 @@ } if (i810_dev == NULL) { - /* Intel 830MP with external graphic card */ - /* It will be initialized later */ + /* Intel 830MP with external graphic card */ + /* It will be initialized later */ agp_bridge.type = INTEL_I830_M; break; } @@ -4690,23 +4911,6 @@ } #endif /* CONFIG_AGP_SWORKS */ - -#ifdef CONFIG_AGP_HP_ZX1 - if (dev->vendor == PCI_VENDOR_ID_HP) { - do { - /* ZX1 LBAs can be either PCI or AGP bridges */ - if (pci_find_capability(dev, PCI_CAP_ID_AGP)) { - printk(KERN_INFO PFX "Detected HP ZX1 AGP " - "chipset at %s\n", dev->slot_name); - agp_bridge.type = HP_ZX1; - agp_bridge.dev = dev; - return hp_zx1_setup(dev); - } - dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, dev); - } while (dev); - return -ENODEV; - } -#endif /* CONFIG_AGP_HP_ZX1 */ #ifdef CONFIG_AGP_HP_ZX1 if (dev->vendor == PCI_VENDOR_ID_HP) { diff -Nru a/drivers/char/drm/drm_agpsupport.h b/drivers/char/drm/drm_agpsupport.h --- a/drivers/char/drm/drm_agpsupport.h Sun Jun 2 18:44:55 2002 +++ b/drivers/char/drm/drm_agpsupport.h Sun Jun 2 18:44:55 2002 @@ -276,6 +276,7 @@ case INTEL_I845: head->chipset = "Intel i845"; break; #endif case INTEL_I850: head->chipset = "Intel i850"; break; + case INTEL_460GX: head->chipset = "Intel 460GX"; break; case VIA_GENERIC: head->chipset = "VIA"; break; case VIA_VP3: head->chipset = "VIA VP3"; break; diff -Nru a/drivers/char/dtlk.c b/drivers/char/dtlk.c --- a/drivers/char/dtlk.c Sun Jun 2 18:44:57 2002 +++ b/drivers/char/dtlk.c Sun Jun 2 18:44:57 2002 @@ -418,12 +418,11 @@ dtlk_portlist[i], (testval = inw_p(dtlk_portlist[i]))); #endif - if (check_region(dtlk_portlist[i], DTLK_IO_EXTENT)) + if (!request_region(dtlk_portlist[i], DTLK_IO_EXTENT, + "dtlk")) continue; testval = inw_p(dtlk_portlist[i]); if ((testval &= 0xfbff) == 0x107f) { - request_region(dtlk_portlist[i], DTLK_IO_EXTENT, - "dtlk"); dtlk_port_lpc = dtlk_portlist[i]; dtlk_port_tts = dtlk_port_lpc + 1; @@ -508,6 +507,7 @@ return 0; } + release_region(dtlk_portlist[i], DTLK_IO_EXTENT); } printk(KERN_INFO "\nDoubleTalk PC - not found\n"); diff -Nru a/drivers/char/efirtc.c b/drivers/char/efirtc.c --- a/drivers/char/efirtc.c Sun Jun 2 18:44:58 2002 +++ b/drivers/char/efirtc.c Sun Jun 2 18:44:58 2002 @@ -375,9 +375,14 @@ static int __init efi_rtc_init(void) { + int ret =0; printk(KERN_INFO "EFI Time Services Driver v%s\n", EFI_RTC_VERSION); - misc_register(&efi_rtc_dev); + ret = misc_register(&efi_rtc_dev); + if (ret) { + printk(KERN_ERR "driver/efirtc: can't misc_register on minor=%d\n", EFI_RTC_MINOR); + return ret; + } create_proc_read_entry ("driver/efirtc", 0, NULL, efi_rtc_read_proc, NULL); diff -Nru a/drivers/char/epca.c b/drivers/char/epca.c --- a/drivers/char/epca.c Sun Jun 2 18:44:58 2002 +++ b/drivers/char/epca.c Sun Jun 2 18:44:58 2002 @@ -2022,7 +2022,8 @@ (*(ushort *)((ulong)memaddr + XEPORTS) < 3)) shrinkmem = 1; if (bd->type < PCIXEM) - request_region((int)bd->port, 4, board_desc[bd->type]); + if (!request_region((int)bd->port, 4, board_desc[bd->type])) + return; memwinon(bd, 0); @@ -2186,9 +2187,13 @@ if (!(ch->tmp_buf)) { printk(KERN_ERR "POST FEP INIT : kmalloc failed for port 0x%x\n",i); - + release_region((int)bd->port, 4); + while(i-- > 0) + kfree((ch--)->tmp_buf); + return; } - memset((void *)ch->tmp_buf,0,ch->txbufsize); + else + memset((void *)ch->tmp_buf,0,ch->txbufsize); } /* End for each port */ printk(KERN_INFO diff -Nru a/drivers/char/esp.c b/drivers/char/esp.c --- a/drivers/char/esp.c Sun Jun 2 18:44:56 2002 +++ b/drivers/char/esp.c Sun Jun 2 18:44:56 2002 @@ -2476,9 +2476,13 @@ } else *region_start = info->port; - request_region(*region_start, + if (!request_region(*region_start, info->port - *region_start + 8, - "esp serial"); + "esp serial")) + { + restore_flags(flags); + return -EIO; + } /* put card in enhanced mode */ /* this prevents access through */ diff -Nru a/drivers/char/h8.c b/drivers/char/h8.c --- a/drivers/char/h8.c Sun Jun 2 18:44:57 2002 +++ b/drivers/char/h8.c Sun Jun 2 18:44:57 2002 @@ -299,9 +299,13 @@ } printk(KERN_INFO "H8 at 0x%x IRQ %d\n", h8_base, h8_irq); - create_proc_info_entry("driver/h8", 0, NULL, h8_get_info); + if (!request_region(h8_base, 8, "h8")) + { + free_irq(h8_irq, NULL); + return -EIO; + } - request_region(h8_base, 8, "h8"); + create_proc_info_entry("driver/h8", 0, NULL, h8_get_info); h8_alloc_queues(); diff -Nru a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/hvc_console.c Sun Jun 2 18:44:58 2002 @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2001 Anton Blanchard , IBM + * Copyright (C) 2001 Paul Mackerras , IBM + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int hvc_count(int *); +extern int hvc_get_chars(int index, char *buf, int count); +extern int hvc_put_chars(int index, const char *buf, int count); + +#define HVC_MAJOR 229 +#define HVC_MINOR 0 + +#define MAX_NR_HVC_CONSOLES 4 + +#define TIMEOUT ((HZ + 99) / 100) + +struct tty_driver hvc_driver; +static int hvc_refcount; +static struct tty_struct *hvc_table[MAX_NR_HVC_CONSOLES]; +static struct termios *hvc_termios[MAX_NR_HVC_CONSOLES]; +static struct termios *hvc_termios_locked[MAX_NR_HVC_CONSOLES]; +static int hvc_offset; + +#define N_OUTBUF 16 + +#define __ALIGNED__ __attribute__((__aligned__(8))) + +struct hvc_struct { + spinlock_t lock; + int index; + struct tty_struct *tty; + unsigned int count; + int do_wakeup; + char outbuf[N_OUTBUF] __ALIGNED__; + int n_outbuf; +}; + +struct hvc_struct hvc_struct[MAX_NR_HVC_CONSOLES]; + +static int hvc_open(struct tty_struct *tty, struct file * filp) +{ + int line = minor(tty->device) - tty->driver.minor_start; + struct hvc_struct *hp; + unsigned long flags; + + if (line < 0 || line >= MAX_NR_HVC_CONSOLES) + return -ENODEV; + hp = &hvc_struct[line]; + + tty->driver_data = hp; + spin_lock_irqsave(&hp->lock, flags); + hp->tty = tty; + hp->count++; + spin_unlock_irqrestore(&hp->lock, flags); + + return 0; +} + +static void hvc_close(struct tty_struct *tty, struct file * filp) +{ + struct hvc_struct *hp = tty->driver_data; + unsigned long flags; + + if (tty_hung_up_p(filp)) + return; + spin_lock_irqsave(&hp->lock, flags); + if (--hp->count == 0) + hp->tty = NULL; + else if (hp->count < 0) + printk(KERN_ERR "hvc_close %lu: oops, count is %d\n", + hp - hvc_struct, hp->count); + spin_unlock_irqrestore(&hp->lock, flags); +} + +/* called with hp->lock held */ +static void hvc_push(struct hvc_struct *hp) +{ + int n; + + n = hvc_put_chars(hp->index + hvc_offset, hp->outbuf, hp->n_outbuf); + if (n <= 0) { + if (n == 0) + return; + /* throw away output on error; this happens when + there is no session connected to the vterm. */ + hp->n_outbuf = 0; + } else + hp->n_outbuf -= n; + if (hp->n_outbuf > 0) + memmove(hp->outbuf, hp->outbuf + n, hp->n_outbuf); + else + hp->do_wakeup = 1; +} + +static int hvc_write(struct tty_struct *tty, int from_user, + const unsigned char *buf, int count) +{ + struct hvc_struct *hp = tty->driver_data; + char *p; + int todo, written = 0; + unsigned long flags; + + spin_lock_irqsave(&hp->lock, flags); + while (count > 0 && (todo = N_OUTBUF - hp->n_outbuf) > 0) { + if (todo > count) + todo = count; + p = hp->outbuf + hp->n_outbuf; + if (from_user) { + todo -= copy_from_user(p, buf, todo); + if (todo == 0) { + if (written == 0) + written = -EFAULT; + break; + } + } else + memcpy(p, buf, todo); + count -= todo; + buf += todo; + hp->n_outbuf += todo; + written += todo; + hvc_push(hp); + } + spin_unlock_irqrestore(&hp->lock, flags); + + return written; +} + +static int hvc_write_room(struct tty_struct *tty) +{ + struct hvc_struct *hp = tty->driver_data; + + return N_OUTBUF - hp->n_outbuf; +} + +static int hvc_chars_in_buffer(struct tty_struct *tty) +{ + struct hvc_struct *hp = tty->driver_data; + + return hp->n_outbuf; +} + +static void hvc_poll(int index) +{ + struct hvc_struct *hp = &hvc_struct[index]; + struct tty_struct *tty; + int i, n; + char buf[16] __ALIGNED__; + unsigned long flags; + + spin_lock_irqsave(&hp->lock, flags); + + if (hp->n_outbuf > 0) + hvc_push(hp); + + tty = hp->tty; + if (tty) { + for (;;) { + if (TTY_FLIPBUF_SIZE - tty->flip.count < sizeof(buf)) + break; + n = hvc_get_chars(index + hvc_offset, buf, sizeof(buf)); + if (n <= 0) + break; + for (i = 0; i < n; ++i) + tty_insert_flip_char(tty, buf[i], 0); + } + if (tty->flip.count) + tty_schedule_flip(tty); + + if (hp->do_wakeup) { + hp->do_wakeup = 0; + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) + && tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + } + } + + spin_unlock_irqrestore(&hp->lock, flags); +} + +int khvcd(void *unused) +{ + int i; + + daemonize(); + reparent_to_init(); + strcpy(current->comm, "khvcd"); + sigfillset(¤t->blocked); + + for (;;) { + for (i = 0; i < MAX_NR_HVC_CONSOLES; ++i) + hvc_poll(i); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(TIMEOUT); + } +} + +int __init hvc_init(void) +{ + int i; + + memset(&hvc_driver, 0, sizeof(struct tty_driver)); + + hvc_driver.magic = TTY_DRIVER_MAGIC; + hvc_driver.driver_name = "hvc"; + hvc_driver.name = "hvc/%d"; + hvc_driver.major = HVC_MAJOR; + hvc_driver.minor_start = HVC_MINOR; + hvc_driver.num = hvc_count(&hvc_offset); + if (hvc_driver.num > MAX_NR_HVC_CONSOLES) + hvc_driver.num = MAX_NR_HVC_CONSOLES; + hvc_driver.type = TTY_DRIVER_TYPE_SYSTEM; + hvc_driver.init_termios = tty_std_termios; + hvc_driver.flags = TTY_DRIVER_REAL_RAW; + hvc_driver.refcount = &hvc_refcount; + hvc_driver.table = hvc_table; + hvc_driver.termios = hvc_termios; + hvc_driver.termios_locked = hvc_termios_locked; + + hvc_driver.open = hvc_open; + hvc_driver.close = hvc_close; + hvc_driver.write = hvc_write; + hvc_driver.write_room = hvc_write_room; + hvc_driver.chars_in_buffer = hvc_chars_in_buffer; + + for (i = 0; i < hvc_driver.num; i++) { + hvc_struct[i].lock = SPIN_LOCK_UNLOCKED; + hvc_struct[i].index = i; + tty_register_devfs(&hvc_driver, 0, hvc_driver.minor_start + i); + } + + if (tty_register_driver(&hvc_driver)) + panic("Couldn't register hvc console driver\n"); + + if (hvc_driver.num > 0) + kernel_thread(khvcd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); + + return 0; +} + +static void __exit hvc_exit(void) +{ +} + +void hvc_console_print(struct console *co, const char *b, unsigned count) +{ + char c[16] __ALIGNED__; + unsigned i, n; + int r, donecr = 0; + + i = n = 0; + while (count > 0 || i > 0) { + if (count > 0 && i < sizeof(c)) { + if (b[n] == '\n' && !donecr) { + c[i++] = '\r'; + donecr = 1; + } else { + c[i++] = b[n++]; + donecr = 0; + --count; + } + } else { + r = hvc_put_chars(co->index + hvc_offset, c, i); + if (r < 0) { + /* throw away chars on error */ + i = 0; + } else if (r > 0) { + i -= r; + if (i > 0) + memmove(c, c+r, i); + } + } + } +} + +static kdev_t hvc_console_device(struct console *c) +{ + return mk_kdev(HVC_MAJOR, HVC_MINOR + c->index); +} + +static int __init hvc_console_setup(struct console *co, char *options) +{ + if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES + || co->index >= hvc_count(&hvc_offset)) + return -1; + return 0; +} + +struct console hvc_con_driver = { + name: "hvc", + write: hvc_console_print, + device: hvc_console_device, + setup: hvc_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; + +int __init hvc_console_init(void) +{ + register_console(&hvc_con_driver); + return 0; +} + +module_init(hvc_init); +module_exit(hvc_exit); diff -Nru a/drivers/char/ib700wdt.c b/drivers/char/ib700wdt.c --- a/drivers/char/ib700wdt.c Sun Jun 2 18:44:57 2002 +++ b/drivers/char/ib700wdt.c Sun Jun 2 18:44:57 2002 @@ -271,11 +271,21 @@ ibwdt_validate_timeout(); spin_lock_init(&ibwdt_lock); - misc_register(&ibwdt_miscdev); + if (misc_register(&ibwdt_miscdev)) + return -ENODEV; #if WDT_START != WDT_STOP - request_region(WDT_STOP, 1, "IB700 WDT"); + if (!request_region(WDT_STOP, 1, "IB700 WDT")) { + misc_deregister(&ibwdt_miscdev); + return -EIO; + } #endif - request_region(WDT_START, 1, "IB700 WDT"); + if (!request_region(WDT_START, 1, "IB700 WDT")) { +#if WDT_START != WDT_STOP + release_region(WDT_STOP, 1); +#endif + misc_deregister(&ibwdt_miscdev); + return -EIO; + } register_reboot_notifier(&ibwdt_notifier); return 0; } diff -Nru a/drivers/char/isicom.c b/drivers/char/isicom.c --- a/drivers/char/isicom.c Sun Jun 2 18:44:56 2002 +++ b/drivers/char/isicom.c Sun Jun 2 18:44:56 2002 @@ -1680,20 +1680,13 @@ { int count, done=0; for (count=0; count < BOARD_COUNT; count++ ) { - if (isi_card[count].base) { - if (check_region(isi_card[count].base,16)) { + if (isi_card[count].base) + if (!request_region(isi_card[count].base,16,ISICOM_NAME)) { printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x is busy. Card%d will be disabled.\n", isi_card[count].base,isi_card[count].base+15,count+1); isi_card[count].base=0; - } - else { - request_region(isi_card[count].base,16,ISICOM_NAME); -#ifdef ISICOM_DEBUG - printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x requested for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1); -#endif done++; } - } } return done; } diff -Nru a/drivers/char/istallion.c b/drivers/char/istallion.c --- a/drivers/char/istallion.c Sun Jun 2 18:44:56 2002 +++ b/drivers/char/istallion.c Sun Jun 2 18:44:56 2002 @@ -3972,17 +3972,16 @@ printk(KERN_DEBUG "stli_initecp(brdp=%x)\n", (int) brdp); #endif -/* - * Do a basic sanity check on the IO and memory addresses. - */ + if (!request_region(brdp->iobase, brdp->iosize, name)) + return -EIO; + if ((brdp->iobase == 0) || (brdp->memaddr == 0)) + { + release_region(brdp->iobase, brdp->iosize); return(-ENODEV); + } brdp->iosize = ECP_IOSIZE; - if (check_region(brdp->iobase, brdp->iosize)) - printk(KERN_ERR "STALLION: Warning, board %d I/O address %x " - "conflicts with another device\n", - brdp->brdnr, brdp->iobase); /* * Based on the specific board type setup the common vars to access @@ -4047,6 +4046,7 @@ break; default: + release_region(brdp->iobase, brdp->iosize); return(-EINVAL); } @@ -4060,7 +4060,10 @@ brdp->membase = ioremap(brdp->memaddr, brdp->memsize); if (brdp->membase == (void *) NULL) + { + release_region(brdp->iobase, brdp->iosize); return(-ENOMEM); + } /* * Now that all specific code is set up, enable the shared memory and @@ -4082,7 +4085,10 @@ #endif if (sig.magic != ECP_MAGIC) + { + release_region(brdp->iobase, brdp->iosize); return(-ENODEV); + } /* * Scan through the signature looking at the panels connected to the @@ -4103,7 +4109,7 @@ brdp->nrpanels++; } - request_region(brdp->iobase, brdp->iosize, name); + brdp->state |= BST_FOUND; return(0); } @@ -4133,10 +4139,9 @@ return(-ENODEV); brdp->iosize = ONB_IOSIZE; - if (check_region(brdp->iobase, brdp->iosize)) - printk(KERN_ERR "STALLION: Warning, board %d I/O address %x " - "conflicts with another device\n", - brdp->brdnr, brdp->iobase); + + if (!request_region(brdp->iobase, brdp->iosize, name)) + return -EIO; /* * Based on the specific board type setup the common vars to access @@ -4211,6 +4216,7 @@ break; default: + release_region(brdp->iobase, brdp->iosize); return(-EINVAL); } @@ -4224,7 +4230,10 @@ brdp->membase = ioremap(brdp->memaddr, brdp->memsize); if (brdp->membase == (void *) NULL) + { + release_region(brdp->iobase, brdp->iosize); return(-ENOMEM); + } /* * Now that all specific code is set up, enable the shared memory and @@ -4244,7 +4253,10 @@ if ((sig.magic0 != ONB_MAGIC0) || (sig.magic1 != ONB_MAGIC1) || (sig.magic2 != ONB_MAGIC2) || (sig.magic3 != ONB_MAGIC3)) + { + release_region(brdp->iobase, brdp->iosize); return(-ENODEV); + } /* * Scan through the signature alive mask and calculate how many ports @@ -4262,7 +4274,7 @@ } brdp->panels[0] = brdp->nrports; - request_region(brdp->iobase, brdp->iosize, name); + brdp->state |= BST_FOUND; return(0); } diff -Nru a/drivers/char/ite_gpio.c b/drivers/char/ite_gpio.c --- a/drivers/char/ite_gpio.c Sun Jun 2 18:44:58 2002 +++ b/drivers/char/ite_gpio.c Sun Jun 2 18:44:58 2002 @@ -391,13 +391,14 @@ { int i; - misc_register(&ite_gpio_miscdev); + if (misc_register(&ite_gpio_miscdev)) + return -ENODEV; - if (check_region(ite_gpio_base, 0x1c) < 0 ) { - return -ENODEV; - } else { - request_region(ite_gpio_base, 0x1c, "ITE GPIO"); - } + if (!request_region(ite_gpio_base, 0x1c, "ITE GPIO")) + { + misc_deregister(&ite_gpio_miscdev); + return -EIO; + } /* initialize registers */ ITE_GPACR = 0xffff; @@ -407,13 +408,18 @@ ITE_GPBICR = 0x00ff; ITE_GPCICR = 0x00ff; ITE_GCR = 0; - + for (i = 0; i < MAX_GPIO_LINE; i++) { ite_gpio_irq_pending[i]=0; init_waitqueue_head(&ite_gpio_wait[i]); } - if (request_irq(ite_gpio_irq, ite_gpio_irq_handler, SA_SHIRQ, "gpio", 0) < 0) + + if (request_irq(ite_gpio_irq, ite_gpio_irq_handler, SA_SHIRQ, "gpio", 0) < 0) { + misc_deregister(&ite_gpio_miscdev); + release_region(ite_gpio_base, 0x1c); return 0; + } + printk("GPIO at 0x%x (irq = %d)\n", ite_gpio_base, ite_gpio_irq); return 0; diff -Nru a/drivers/char/mixcomwd.c b/drivers/char/mixcomwd.c --- a/drivers/char/mixcomwd.c Sun Jun 2 18:44:56 2002 +++ b/drivers/char/mixcomwd.c Sun Jun 2 18:44:56 2002 @@ -247,11 +247,15 @@ return -ENODEV; } - request_region(watchdog_port,1,"MixCOM watchdog"); + if (!request_region(watchdog_port,1,"MixCOM watchdog")) + return -EIO; ret = misc_register(&mixcomwd_miscdev); if (ret) + { + release_region(watchdog_port, 1); return ret; + } printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",VERSION,watchdog_port); diff -Nru a/drivers/char/pc_keyb.c b/drivers/char/pc_keyb.c --- a/drivers/char/pc_keyb.c Sun Jun 2 18:44:57 2002 +++ b/drivers/char/pc_keyb.c Sun Jun 2 18:44:57 2002 @@ -808,6 +808,17 @@ { int status; +#ifdef CONFIG_IA64 + /* + * This is not really IA-64 specific. Probably ought to be done on all platforms + * that are (potentially) legacy-free. + */ + if (kbd_read_status() == 0xff && kbd_read_input() == 0xff) { + kbd_exists = 0; + return "No keyboard controller preset"; + } +#endif + /* * Test the keyboard interface. * This seems to be the only way to get it going. @@ -910,6 +921,10 @@ char *msg = initialize_kbd(); if (msg) printk(KERN_WARNING "initialize_kbd: %s\n", msg); +#ifdef CONFIG_IA64 + if (!kbd_exists) + return; +#endif } #if defined CONFIG_PSMOUSE diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c --- a/drivers/char/raw.c Sun Jun 2 18:44:56 2002 +++ b/drivers/char/raw.c Sun Jun 2 18:44:56 2002 @@ -34,6 +34,7 @@ int raw_open(struct inode *, struct file *); int raw_release(struct inode *, struct file *); int raw_ctl_ioctl(struct inode *, struct file *, unsigned int, unsigned long); +int raw_ioctl(struct inode *, struct file *, unsigned int, unsigned long); static struct file_operations raw_fops = { @@ -41,6 +42,7 @@ write: raw_write, open: raw_open, release: raw_release, + ioctl: raw_ioctl, }; static struct file_operations raw_ctl_fops = { @@ -142,6 +144,25 @@ } + +/* Forward ioctls to the underlying block device. */ +int raw_ioctl(struct inode *inode, + struct file *flip, + unsigned int command, + unsigned long arg) +{ + int minor = minor(inode->i_rdev), err; + struct block_device *b; + if (minor < 1 && minor > 255) + return -ENODEV; + + b = raw_devices[minor].binding; + err = -EINVAL; + if (b && b->bd_inode && b->bd_op && b->bd_op->ioctl) { + err = b->bd_op->ioctl(b->bd_inode, NULL, command, arg); + } + return err; +} /* * Deal with ioctls against the raw-device control interface, to bind diff -Nru a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c --- a/drivers/char/rio/rioctrl.c Sun Jun 2 18:44:57 2002 +++ b/drivers/char/rio/rioctrl.c Sun Jun 2 18:44:57 2002 @@ -139,7 +139,7 @@ rio_dprintk (RIO_DEBUG_CTRL, "Copying %d bytes from user %p to %p.\n", siz, (void *)arg, dp); rv = copy_from_user (dp, (void *)arg, siz); - if (rv < 0) return COPYFAIL; + if (rv) return COPYFAIL; else return rv; } @@ -150,7 +150,7 @@ rio_dprintk (RIO_DEBUG_CTRL, "Copying %d bytes to user %p from %p.\n", siz, (void *)arg, dp); rv = copy_to_user ((void *)arg, dp, siz); - if (rv < 0) return COPYFAIL; + if (rv) return COPYFAIL; else return rv; } diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c --- a/drivers/char/rtc.c Sun Jun 2 18:44:57 2002 +++ b/drivers/char/rtc.c Sun Jun 2 18:44:57 2002 @@ -69,6 +69,7 @@ #include #include #include +#include #include #include @@ -140,6 +141,7 @@ static unsigned long rtc_status = 0; /* bitmapped status byte. */ static unsigned long rtc_freq = 0; /* Current periodic IRQ rate */ static unsigned long rtc_irq_data = 0; /* our output to the world */ +static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */ #if RTC_IRQ static spinlock_t rtc_task_lock = SPIN_LOCK_UNLOCKED; @@ -198,6 +200,38 @@ #endif /* + * sysctl-tuning infrastructure. + */ +static ctl_table rtc_table[] = { + { 1, "max-user-freq", &rtc_max_user_freq, sizeof(int), 0644, NULL, + &proc_dointvec, NULL, }, + { 0, } +}; + +static ctl_table rtc_root[] = { + { 1, "rtc", NULL, 0, 0555, rtc_table, }, + { 0, } +}; + +static ctl_table dev_root[] = { + { CTL_DEV, "dev", NULL, 0, 0555, rtc_root, }, + { 0, } +}; + +static struct ctl_table_header *sysctl_header; + +static int __init init_sysctl(void) +{ + sysctl_header = register_sysctl_table(dev_root, 0); + return 0; +} + +static void __exit cleanup_sysctl(void) +{ + unregister_sysctl_table(sysctl_header); +} + +/* * Now all the various file operations that we export. */ @@ -305,7 +339,8 @@ * We don't really want Joe User enabling more * than 64Hz of interrupts on a multi-user machine. */ - if (!kernel && (rtc_freq > 64) && (!capable(CAP_SYS_RESOURCE))) + if (!kernel && (rtc_freq > rtc_max_user_freq) && + (!capable(CAP_SYS_RESOURCE))) return -EACCES; if (!(rtc_status & RTC_TIMER_ON)) { @@ -503,7 +538,7 @@ * We don't really want Joe User generating more * than 64Hz of interrupts on a multi-user machine. */ - if (!kernel && (arg > 64) && (!capable(CAP_SYS_RESOURCE))) + if (!kernel && (arg > rtc_max_user_freq) && (!capable(CAP_SYS_RESOURCE))) return -EACCES; while (arg > (1< + * (c) Copyright 2001 Scott Jennings * * 4/19 - 2001 [Initial revision] + * 9/27 - 2001 Added spinlocking * * * Theory of operation: @@ -88,8 +89,9 @@ static void wdt_timer_ping(unsigned long); static struct timer_list timer; static unsigned long next_heartbeat; -static int wdt_is_open; +static unsigned long wdt_is_open; static int wdt_expect_close; +static spinlock_t wdt_spinlock; /* * Whack the dog @@ -102,11 +104,18 @@ */ if(time_before(jiffies, next_heartbeat)) { + /* Ping the WDT */ + spin_lock(&wdt_spinlock); + /* Ping the WDT by reading from WDT_PING */ inb_p(WDT_PING); + /* Re-set the timer interval */ timer.expires = jiffies + WDT_INTERVAL; add_timer(&timer); + + spin_unlock(&wdt_spinlock); + } else { printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n"); } @@ -118,19 +127,24 @@ static void wdt_change(int writeval) { + unsigned long flags; + spin_lock_irqsave(&wdt_spinlock, flags); + /* buy some time */ inb_p(WDT_PING); /* make W83877F available */ - outb_p(ENABLE_W83877F,ENABLE_W83877F_PORT); - outb_p(ENABLE_W83877F,ENABLE_W83877F_PORT); + outb_p(ENABLE_W83877F, ENABLE_W83877F_PORT); + outb_p(ENABLE_W83877F, ENABLE_W83877F_PORT); /* enable watchdog */ - outb_p(WDT_REGISTER,ENABLE_W83877F_PORT); - outb_p(writeval,ENABLE_W83877F_PORT+1); + outb_p(WDT_REGISTER, ENABLE_W83877F_PORT); + outb_p(writeval, ENABLE_W83877F_PORT+1); /* lock the W8387FF away */ - outb_p(DISABLE_W83877F,ENABLE_W83877F_PORT); + outb_p(DISABLE_W83877F, ENABLE_W83877F_PORT); + + spin_unlock_irqrestore(&wdt_spinlock, flags); } static void wdt_startup(void) @@ -178,7 +192,7 @@ /* now scan */ for(ofs = 0; ofs != count; ofs++) - if(buf[ofs] == 'V') + if(buf[ofs] == 'V') wdt_expect_close = 1; /* someone wrote to us, we should restart timer */ @@ -200,10 +214,10 @@ { case WATCHDOG_MINOR: /* Just in case we're already talking to someone... */ - if(wdt_is_open) + if(test_and_set_bit(0, &wdt_is_open)) { return -EBUSY; + } /* Good, fire up the show */ - wdt_is_open = 1; wdt_startup(); return 0; @@ -305,6 +319,8 @@ { int rc = -EBUSY; + spin_lock_init(&wdt_spinlock); + if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT")) goto err_out; if (!request_region(WDT_PING, 1, "W8387FF WDT")) @@ -339,4 +355,7 @@ module_init(w83877f_wdt_init); module_exit(w83877f_wdt_unload); +MODULE_AUTHOR("Scott and Bill Jennings"); +MODULE_DESCRIPTION("Driver for watchdog timer in w83877f chip"); MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; diff -Nru a/drivers/ide/Makefile b/drivers/ide/Makefile --- a/drivers/ide/Makefile Sun Jun 2 18:44:58 2002 +++ b/drivers/ide/Makefile Sun Jun 2 18:44:58 2002 @@ -8,7 +8,7 @@ # In the future, some of these should be built conditionally. # -export-objs := ide-taskfile.o main.o ide.o probe.o quirks.o pcidma.o tcq.o \ +export-objs := device.o ide-taskfile.o main.o ide.o probe.o quirks.o pcidma.o tcq.o \ atapi.o ataraid.o obj-$(CONFIG_BLK_DEV_HD) += hd.o @@ -68,7 +68,7 @@ obj-$(CONFIG_BLK_DEV_ATARAID_PDC) += pdcraid.o obj-$(CONFIG_BLK_DEV_ATARAID_HPT) += hptraid.o -ide-mod-objs := ide-taskfile.o main.o ide.o probe.o \ +ide-mod-objs := device.o ide-taskfile.o main.o ide.o probe.o \ ioctl.o atapi.o ata-timing.o $(ide-obj-y) include $(TOPDIR)/Rules.make diff -Nru a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c --- a/drivers/ide/aec62xx.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ide/aec62xx.c Sun Jun 2 18:44:57 2002 @@ -54,6 +54,12 @@ #define AEC_IDE_ENABLE 0x4a #define AEC_UDMA_OLD 0x54 +#define AEC_BM_STAT_PCH 0x02 +#define AEC_BM_STAT_SCH 0x0a + +#define AEC_PLLCLK_ATA133 0x10 +#define AEC_CABLEPINS_INPUT 0x10 + static unsigned char aec_cyc2udma[17] = { 0, 0, 7, 6, 5, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1 }; /* @@ -144,8 +150,9 @@ } #ifdef CONFIG_BLK_DEV_IDEDMA -static int aec62xx_dmaproc(struct ata_device *drive) +static int aec62xx_udma_setup(struct ata_device *drive) { + u32 bmide = pci_resource_start(drive->channel->pci_dev, 4); short speed; int map; @@ -155,7 +162,9 @@ switch (drive->channel->pci_dev->device) { case PCI_DEVICE_ID_ARTOP_ATP865R: case PCI_DEVICE_ID_ARTOP_ATP865: - map |= XFER_UDMA_100 | XFER_UDMA_133; + /* Can't use these modes simultaneously, + based on which PLL clock was chosen. */ + map |= inb (bmide + AEC_BM_STAT_PCH) & AEC_PLLCLK_ATA133 ? XFER_UDMA_133 : XFER_UDMA_100; case PCI_DEVICE_ID_ARTOP_ATP860R: case PCI_DEVICE_ID_ARTOP_ATP860: map |= XFER_UDMA_66; @@ -172,10 +181,12 @@ /* * The initialization callback. Here we determine the IDE chip type * and initialize its drive independent registers. + * We return the IRQ assigned to the chip. */ static unsigned int __init aec62xx_init_chipset(struct pci_dev *dev) { + u32 bmide = pci_resource_start(dev, 4); unsigned char t; /* @@ -202,8 +213,9 @@ /* Enable burst mode. */ pci_read_config_byte(dev, AEC_IDE_ENABLE, &t); pci_write_config_byte(dev, AEC_IDE_ENABLE, t | 0x80); - #endif + /* switch cable detection pins to input-only. */ + outb (inb (bmide + AEC_BM_STAT_SCH) | AEC_CABLEPINS_INPUT, bmide + AEC_BM_STAT_SCH); } /* @@ -214,7 +226,7 @@ printk(KERN_INFO "AEC_IDE: %s (rev %02x) controller on pci%s\n", dev->name, t, dev->slot_name); - return 0; + return dev->irq; } static unsigned int __init aec62xx_ata66_check(struct ata_channel *ch) @@ -232,8 +244,8 @@ { int i; - ch->tuneproc = &aec62xx_tune_drive; - ch->speedproc = &aec_set_drive; + ch->tuneproc = aec62xx_tune_drive; + ch->speedproc = aec_set_drive; ch->autodma = 0; ch->io_32bit = 1; @@ -247,7 +259,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA if (ch->dma_base) { ch->highmem = 1; - ch->XXX_udma = aec62xx_dmaproc; + ch->udma_setup = aec62xx_udma_setup; #ifdef CONFIG_IDEDMA_AUTO if (!noautodma) ch->autodma = 1; diff -Nru a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c --- a/drivers/ide/alim15x3.c Sun Jun 2 18:44:58 2002 +++ b/drivers/ide/alim15x3.c Sun Jun 2 18:44:58 2002 @@ -29,215 +29,9 @@ #include "ata-timing.h" #include "pcihost.h" -#undef DISPLAY_ALI_TIMINGS - -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int ali_get_info(char *buffer, char **addr, off_t offset, int count); -extern int (*ali_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -char *fifo[4] = { - "FIFO Off", - "FIFO On ", - "DMA mode", - "PIO mode" }; - -char *udmaT[8] = { - "1.5T", - " 2T", - "2.5T", - " 3T", - "3.5T", - " 4T", - " 6T", - " 8T" -}; - -char *channel_status[8] = { - "OK ", - "busy ", - "DRQ ", - "DRQ busy ", - "error ", - "error busy ", - "error DRQ ", - "error DRQ busy" -}; - -static int ali_get_info (char *buffer, char **addr, off_t offset, int count) -{ - byte reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1; - unsigned int bibma; - byte c0, c1; - byte rev, tmp; - char *p = buffer; - char *q; - - /* fetch rev. */ - pci_read_config_byte(bmide_dev, 0x08, &rev); - if (rev >= 0xc1) /* M1543C or newer */ - udmaT[7] = " ???"; - else - fifo[3] = " ??? "; - - /* first fetch bibma: */ - pci_read_config_dword(bmide_dev, 0x20, &bibma); - bibma = (bibma & 0xfff0) ; - /* - * at that point bibma+0x2 et bibma+0xa are byte - * registers to investigate: - */ - c0 = inb((unsigned short)bibma + 0x02); - c1 = inb((unsigned short)bibma + 0x0a); - - p += sprintf(p, - "\n Ali M15x3 Chipset.\n"); - p += sprintf(p, - " ------------------\n"); - pci_read_config_byte(bmide_dev, 0x78, ®53h); - p += sprintf(p, "PCI Clock: %d.\n", reg53h); - - pci_read_config_byte(bmide_dev, 0x53, ®53h); - p += sprintf(p, - "CD_ROM FIFO:%s, CD_ROM DMA:%s\n", - (reg53h & 0x02) ? "Yes" : "No ", - (reg53h & 0x01) ? "Yes" : "No " ); - pci_read_config_byte(bmide_dev, 0x74, ®53h); - p += sprintf(p, - "FIFO Status: contains %d Words, runs%s%s\n\n", - (reg53h & 0x3f), - (reg53h & 0x40) ? " OVERWR" : "", - (reg53h & 0x80) ? " OVERRD." : "." ); - - p += sprintf(p, - "-------------------primary channel-------------------secondary channel---------\n\n"); - - pci_read_config_byte(bmide_dev, 0x09, ®53h); - p += sprintf(p, - "channel status: %s %s\n", - (reg53h & 0x20) ? "On " : "Off", - (reg53h & 0x10) ? "On " : "Off" ); - - p += sprintf(p, - "both channels togth: %s %s\n", - (c0&0x80) ? "No " : "Yes", - (c1&0x80) ? "No " : "Yes" ); - - pci_read_config_byte(bmide_dev, 0x76, ®53h); - p += sprintf(p, - "Channel state: %s %s\n", - channel_status[reg53h & 0x07], - channel_status[(reg53h & 0x70) >> 4] ); - - pci_read_config_byte(bmide_dev, 0x58, ®5xh); - pci_read_config_byte(bmide_dev, 0x5c, ®5yh); - p += sprintf(p, - "Add. Setup Timing: %dT %dT\n", - (reg5xh & 0x07) ? (reg5xh & 0x07) : 8, - (reg5yh & 0x07) ? (reg5yh & 0x07) : 8 ); - - pci_read_config_byte(bmide_dev, 0x59, ®5xh); - pci_read_config_byte(bmide_dev, 0x5d, ®5yh); - p += sprintf(p, - "Command Act. Count: %dT %dT\n" - "Command Rec. Count: %dT %dT\n\n", - (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, - (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, - (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16, - (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 ); - - p += sprintf(p, - "----------------drive0-----------drive1------------drive0-----------drive1------\n\n"); - p += sprintf(p, - "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "Yes" : "No ", - (c0&0x40) ? "Yes" : "No ", - (c1&0x20) ? "Yes" : "No ", - (c1&0x40) ? "Yes" : "No " ); - - pci_read_config_byte(bmide_dev, 0x54, ®5xh); - pci_read_config_byte(bmide_dev, 0x55, ®5yh); - q = "FIFO threshold: %2d Words %2d Words %2d Words %2d Words\n"; - if (rev < 0xc1) { - if ((rev == 0x20) && (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) { - p += sprintf(p, q, 8, 8, 8, 8); - } else { - p += sprintf(p, q, - (reg5xh & 0x03) + 12, - ((reg5xh & 0x30)>>4) + 12, - (reg5yh & 0x03) + 12, - ((reg5yh & 0x30)>>4) + 12 ); - } - } else { - int t1 = (tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4; - int t2 = (tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4; - int t3 = (tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4; - int t4 = (tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4; - p += sprintf(p, q, t1, t2, t3, t4); - } - -#if 0 - p += sprintf(p, - "FIFO threshold: %2d Words %2d Words %2d Words %2d Words\n", - (reg5xh & 0x03) + 12, - ((reg5xh & 0x30)>>4) + 12, - (reg5yh & 0x03) + 12, - ((reg5yh & 0x30)>>4) + 12 ); -#endif - - p += sprintf(p, - "FIFO mode: %s %s %s %s\n", - fifo[((reg5xh & 0x0c) >> 2)], - fifo[((reg5xh & 0xc0) >> 6)], - fifo[((reg5yh & 0x0c) >> 2)], - fifo[((reg5yh & 0xc0) >> 6)] ); - - pci_read_config_byte(bmide_dev, 0x5a, ®5xh); - pci_read_config_byte(bmide_dev, 0x5b, ®5xh1); - pci_read_config_byte(bmide_dev, 0x5e, ®5yh); - pci_read_config_byte(bmide_dev, 0x5f, ®5yh1); - - p += sprintf(p,/* - "------------------drive0-----------drive1------------drive0-----------drive1------\n")*/ - "Dt RW act. Cnt %2dT %2dT %2dT %2dT\n" - "Dt RW rec. Cnt %2dT %2dT %2dT %2dT\n\n", - (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, - (reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8, - (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, - (reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8, - (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16, - (reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16, - (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16, - (reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 ); - - p += sprintf(p, - "-----------------------------------UDMA Timings--------------------------------\n\n"); - - pci_read_config_byte(bmide_dev, 0x56, ®5xh); - pci_read_config_byte(bmide_dev, 0x57, ®5yh); - p += sprintf(p, - "UDMA: %s %s %s %s\n" - "UDMA timings: %s %s %s %s\n\n", - (reg5xh & 0x08) ? "OK" : "No", - (reg5xh & 0x80) ? "OK" : "No", - (reg5yh & 0x08) ? "OK" : "No", - (reg5yh & 0x80) ? "OK" : "No", - udmaT[(reg5xh & 0x07)], - udmaT[(reg5xh & 0x70) >> 4], - udmaT[reg5yh & 0x07], - udmaT[(reg5yh & 0x70) >> 4] ); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ - static byte m5229_revision; static byte chip_is_1543c_e; -byte ali_proc = 0; static struct pci_dev *isa_dev; static void ali15x3_tune_drive(struct ata_device *drive, byte pio) @@ -405,7 +199,7 @@ return !ali15x3_tune_chipset(drive, mode); } -static int ali15x3_config_drive_for_dma(struct ata_device *drive) +static int ali15x3_udma_setup(struct ata_device *drive) { struct hd_driveid *id = drive->id; struct ata_channel *hwif = drive->channel; @@ -467,17 +261,12 @@ return 0; } -static int ali15x3_udma_write(struct ata_device *drive, struct request *rq) +static int ali15x3_udma_init(struct ata_device *drive, struct request *rq) { if ((m5229_revision < 0xC2) && (drive->type != ATA_DISK)) return 1; /* try PIO instead of DMA */ - return ata_do_udma(0, drive, rq); -} - -static int ali15x3_dmaproc(struct ata_device *drive) -{ - return ali15x3_config_drive_for_dma(drive); + return udma_pci_init(drive, rq); } #endif @@ -503,14 +292,6 @@ printk("%s: simplex device: DMA will fail!!\n", dev->name); } -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) - if (!ali_proc) { - ali_proc = 1; - bmide_dev = dev; - ali_display_info = &ali_get_info; - } -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ - return 0; } @@ -661,8 +442,8 @@ /* * M1543C or newer for DMAing */ - hwif->udma_write = ali15x3_udma_write; - hwif->XXX_udma = ali15x3_dmaproc; + hwif->udma_init = ali15x3_udma_init; + hwif->udma_setup = ali15x3_udma_setup; hwif->autodma = 1; } diff -Nru a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c --- a/drivers/ide/amd74xx.c Sun Jun 2 18:44:58 2002 +++ b/drivers/ide/amd74xx.c Sun Jun 2 18:44:58 2002 @@ -89,108 +89,10 @@ static unsigned int amd_80w; static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3 }; +#if 0 static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 1 }; -static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100" }; - -/* - * AMD /proc entry. - */ - -#if 0 && defined(CONFIG_PROC_FS) - -#include -#include - -byte amd74xx_proc; -int amd_base; -static struct pci_dev *bmide_dev; -extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ - -#define amd_print(format, arg...) p += sprintf(p, format "\n" , ## arg) -#define amd_print_drive(name, format, arg...)\ - p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n"); - -static int amd_get_info(char *buffer, char **addr, off_t offset, int count) -{ - int speed[4], cycle[4], setup[4], active[4], recover[4], den[4], - uen[4], udma[4], active8b[4], recover8b[4]; - struct pci_dev *dev = bmide_dev; - unsigned int v, u, i; - unsigned short c, w; - unsigned char t; - char *p = buffer; - - amd_print("----------AMD BusMastering IDE Configuration----------------"); - - amd_print("Driver Version: 2.8"); - amd_print("South Bridge: %s", bmide_dev->name); - - pci_read_config_byte(dev, PCI_REVISION_ID, &t); - amd_print("Revision: IDE %#x", t); - amd_print("Highest DMA rate: %s", amd_dma[amd_config->flags & AMD_UDMA]); - - amd_print("BM-DMA base: %#x", amd_base); - amd_print("PCI clock: %d.%dMHz", system_bus_speed / 1000, system_bus_speed / 100 % 10); - - amd_print("-----------------------Primary IDE-------Secondary IDE------"); - - pci_read_config_byte(dev, AMD_IDE_CONFIG, &t); - amd_print("Prefetch Buffer: %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x20) ? "yes" : "no"); - amd_print("Post Write Buffer: %10s%20s", (t & 0x40) ? "yes" : "no", (t & 0x10) ? "yes" : "no"); - - pci_read_config_byte(dev, AMD_IDE_ENABLE, &t); - amd_print("Enabled: %10s%20s", (t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no"); - - c = inb(amd_base + 0x02) | (inb(amd_base + 0x0a) << 8); - amd_print("Simplex only: %10s%20s", (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no"); - - amd_print("Cable Type: %10s%20s", (amd_80w & 1) ? "80w" : "40w", (amd_80w & 2) ? "80w" : "40w"); - - if (!system_bus_speed) - return p - buffer; - - amd_print("-------------------drive0----drive1----drive2----drive3-----"); - - pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t); - pci_read_config_dword(dev, AMD_DRIVE_TIMING, &v); - pci_read_config_word(dev, AMD_8BIT_TIMING, &w); - pci_read_config_dword(dev, AMD_UDMA_TIMING, &u); - - for (i = 0; i < 4; i++) { - setup[i] = ((t >> ((3 - i) << 1)) & 0x3) + 1; - recover8b[i] = ((w >> ((1 - (i >> 1)) << 3)) & 0xf) + 1; - active8b[i] = ((w >> (((1 - (i >> 1)) << 3) + 4)) & 0xf) + 1; - active[i] = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1; - recover[i] = ((v >> ((3 - i) << 3)) & 0xf) + 1; - - udma[i] = amd_udma2cyc[((u >> ((3 - i) << 3)) & 0x7)]; - uen[i] = ((u >> ((3 - i) << 3)) & 0x40) ? 1 : 0; - den[i] = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2)); - - if (den[i] && uen[i] && udma[i] == 1) { - speed[i] = system_bus_speed * 3; - cycle[i] = 666666 / system_bus_speed; - continue; - } - - speed[i] = 4 * system_bus_speed / ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2); - cycle[i] = 1000000 * ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2) / system_bus_speed / 2; - } - - amd_print_drive("Transfer Mode: ", "%10s", den[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO"); - - amd_print_drive("Address Setup: ", "%8dns", 1000000 * setup[i] / system_bus_speed); - amd_print_drive("Cmd Active: ", "%8dns", 1000000 * active8b[i] / system_bus_speed); - amd_print_drive("Cmd Recovery: ", "%8dns", 1000000 * recover8b[i] / system_bus_speed); - amd_print_drive("Data Active: ", "%8dns", 1000000 * active[i] / system_bus_speed); - amd_print_drive("Data Recovery: ", "%8dns", 1000000 * recover[i] / system_bus_speed); - amd_print_drive("Cycle Time: ", "%8dns", cycle[i]); - amd_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 1000, speed[i] / 100 % 10); - - return p - buffer; /* hoping it is less than 4K... */ -} - #endif +static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100" }; /* * amd_set_speed() writes timing values to the chipset registers @@ -275,7 +177,7 @@ } #ifdef CONFIG_BLK_DEV_IDEDMA -int amd74xx_dmaproc(struct ata_device *drive) +static int amd74xx_udma_setup(struct ata_device *drive) { short w80 = drive->channel->udma_four; @@ -362,19 +264,6 @@ printk(KERN_INFO "AMD_IDE: %s (rev %02x) %s controller on pci%s\n", dev->name, t, amd_dma[amd_config->flags & AMD_UDMA], dev->slot_name); -/* - * Register /proc/ide/amd74xx entry - */ - -#if 0 && defined(CONFIG_PROC_FS) - if (!amd74xx_proc) { - amd_base = pci_resource_start(dev, 4); - bmide_dev = dev; - amd74xx_display_info = &amd_get_info; - amd74xx_proc = 1; - } -#endif - return 0; } @@ -402,7 +291,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { hwif->highmem = 1; - hwif->XXX_udma = amd74xx_dmaproc; + hwif->udma_setup = amd74xx_udma_setup; # ifdef CONFIG_IDEDMA_AUTO if (!noautodma) hwif->autodma = 1; diff -Nru a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c --- a/drivers/ide/cmd64x.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ide/cmd64x.c Sun Jun 2 18:44:57 2002 @@ -82,123 +82,6 @@ #define UDIDETCR1 0x7B #define DTPR1 0x7C -#undef DISPLAY_CMD64X_TIMINGS - -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int cmd64x_get_info(char *, char **, off_t, int); -static int cmd680_get_info(char *, char **, off_t, int); -extern int (*cmd64x_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u8 reg53 = 0, reg54 = 0, reg55 = 0, reg56 = 0; /* primary */ - u8 reg57 = 0, reg58 = 0, reg5b; /* secondary */ - u8 reg72 = 0, reg73 = 0; /* primary */ - u8 reg7a = 0, reg7b = 0; /* secondary */ - u8 reg50 = 0, reg71 = 0; /* extra */ - u8 hi_byte = 0, lo_byte = 0; - - switch(bmide_dev->device) { - case PCI_DEVICE_ID_CMD_649: - p += sprintf(p, "\n CMD649 Chipset.\n"); - break; - case PCI_DEVICE_ID_CMD_648: - p += sprintf(p, "\n CMD648 Chipset.\n"); - break; - case PCI_DEVICE_ID_CMD_646: - p += sprintf(p, "\n CMD646 Chipset.\n"); - break; - case PCI_DEVICE_ID_CMD_643: - p += sprintf(p, "\n CMD643 Chipset.\n"); - break; - default: - p += sprintf(p, "\n CMD64? Chipse.\n"); - break; - } - (void) pci_read_config_byte(bmide_dev, CFR, ®50); - (void) pci_read_config_byte(bmide_dev, ARTTIM0, ®53); - (void) pci_read_config_byte(bmide_dev, DRWTIM0, ®54); - (void) pci_read_config_byte(bmide_dev, ARTTIM1, ®55); - (void) pci_read_config_byte(bmide_dev, DRWTIM1, ®56); - (void) pci_read_config_byte(bmide_dev, ARTTIM2, ®57); - (void) pci_read_config_byte(bmide_dev, DRWTIM2, ®58); - (void) pci_read_config_byte(bmide_dev, DRWTIM3, ®5b); - (void) pci_read_config_byte(bmide_dev, MRDMODE, ®71); - (void) pci_read_config_byte(bmide_dev, BMIDESR0, ®72); - (void) pci_read_config_byte(bmide_dev, UDIDETCR0, ®73); - (void) pci_read_config_byte(bmide_dev, BMIDESR1, ®7a); - (void) pci_read_config_byte(bmide_dev, UDIDETCR1, ®7b); - - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (reg72&0x80)?"dis":" en",(reg7a&0x80)?"dis":" en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (reg72&0x20)?"yes":"no ",(reg72&0x40)?"yes":"no ",(reg7a&0x20)?"yes":"no ",(reg7a&0x40)?"yes":"no "); - p += sprintf(p, "DMA Mode: %s(%s) %s(%s) %s(%s) %s(%s)\n", - (reg72&0x20)?((reg73&0x01)?"UDMA":" DMA"):" PIO", - (reg72&0x20)?( ((reg73&0x30)==0x30)?(((reg73&0x35)==0x35)?"3":"0"): - ((reg73&0x20)==0x20)?(((reg73&0x25)==0x25)?"3":"1"): - ((reg73&0x10)==0x10)?(((reg73&0x15)==0x15)?"4":"2"): - ((reg73&0x00)==0x00)?(((reg73&0x05)==0x05)?"5":"2"):"X"):"?", - (reg72&0x40)?((reg73&0x02)?"UDMA":" DMA"):" PIO", - (reg72&0x40)?( ((reg73&0xC0)==0xC0)?(((reg73&0xC5)==0xC5)?"3":"0"): - ((reg73&0x80)==0x80)?(((reg73&0x85)==0x85)?"3":"1"): - ((reg73&0x40)==0x40)?(((reg73&0x4A)==0x4A)?"4":"2"): - ((reg73&0x00)==0x00)?(((reg73&0x0A)==0x0A)?"5":"2"):"X"):"?", - (reg7a&0x20)?((reg7b&0x01)?"UDMA":" DMA"):" PIO", - (reg7a&0x20)?( ((reg7b&0x30)==0x30)?(((reg7b&0x35)==0x35)?"3":"0"): - ((reg7b&0x20)==0x20)?(((reg7b&0x25)==0x25)?"3":"1"): - ((reg7b&0x10)==0x10)?(((reg7b&0x15)==0x15)?"4":"2"): - ((reg7b&0x00)==0x00)?(((reg7b&0x05)==0x05)?"5":"2"):"X"):"?", - (reg7a&0x40)?((reg7b&0x02)?"UDMA":" DMA"):" PIO", - (reg7a&0x40)?( ((reg7b&0xC0)==0xC0)?(((reg7b&0xC5)==0xC5)?"3":"0"): - ((reg7b&0x80)==0x80)?(((reg7b&0x85)==0x85)?"3":"1"): - ((reg7b&0x40)==0x40)?(((reg7b&0x4A)==0x4A)?"4":"2"): - ((reg7b&0x00)==0x00)?(((reg7b&0x0A)==0x0A)?"5":"2"):"X"):"?" ); - p += sprintf(p, "PIO Mode: %s %s %s %s\n", - "?", "?", "?", "?"); - p += sprintf(p, " %s %s\n", - (reg50 & CFR_INTR_CH0) ? "interrupting" : "polling ", - (reg57 & ARTTIM23_INTR_CH1) ? "interrupting" : "polling"); - p += sprintf(p, " %s %s\n", - (reg71 & MRDMODE_INTR_CH0) ? "pending" : "clear ", - (reg71 & MRDMODE_INTR_CH1) ? "pending" : "clear"); - p += sprintf(p, " %s %s\n", - (reg71 & MRDMODE_BLK_CH0) ? "blocked" : "enabled", - (reg71 & MRDMODE_BLK_CH1) ? "blocked" : "enabled"); - - SPLIT_BYTE(reg50, hi_byte, lo_byte); - p += sprintf(p, "CFR = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg50, hi_byte, lo_byte); - SPLIT_BYTE(reg57, hi_byte, lo_byte); - p += sprintf(p, "ARTTIM23 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg57, hi_byte, lo_byte); - SPLIT_BYTE(reg71, hi_byte, lo_byte); - p += sprintf(p, "MRDMODE = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg71, hi_byte, lo_byte); - - return p-buffer; /* => must be less than 4k! */ -} - -static int cmd680_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - p += sprintf(p, "\n CMD680 Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "PIO Mode: %s %s %s %s\n", - "?", "?", "?", "?"); - return p-buffer; /* => must be less than 4k! */ -} - -#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte cmd64x_proc = 0; -byte cmd680_proc = 0; - /* * Registers and masks for easy access by drive index: */ @@ -744,7 +627,7 @@ return 0; } -static int cmd680_dmaproc(struct ata_device *drive) +static int cmd680_udma_setup(struct ata_device *drive) { return cmd64x_config_drive_for_dma(drive); } @@ -797,7 +680,7 @@ return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ } -static int cmd64x_dmaproc(struct ata_device *drive) +static int cmd64x_udma_setup(struct ata_device *drive) { return cmd64x_config_drive_for_dma(drive); } @@ -820,7 +703,7 @@ * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old * event order for DMA transfers. */ -static int cmd646_1_dmaproc(struct ata_device *drive) +static int cmd646_1_udma_setup(struct ata_device *drive) { return cmd64x_config_drive_for_dma(drive); } @@ -887,13 +770,6 @@ pci_write_config_dword(dev, 0xB8, 0x4392); pci_write_config_dword(dev, 0xBC, 0x4009); -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) - if (!cmd64x_proc) { - cmd64x_proc = 1; - bmide_dev = dev; - cmd64x_display_info = &cmd680_get_info; - } -#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ return 0; } @@ -975,14 +851,6 @@ (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0); #endif /* CONFIG_PPC */ -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) - if (!cmd64x_proc) { - cmd64x_proc = 1; - bmide_dev = dev; - cmd64x_display_info = &cmd64x_get_info; - } -#endif - return 0; } @@ -1035,7 +903,7 @@ hwif->busproc = cmd680_busproc; #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) - hwif->XXX_udma = cmd680_dmaproc; + hwif->udma_setup = cmd680_udma_setup; #endif hwif->resetproc = cmd680_reset; hwif->speedproc = cmd680_tune_chipset; @@ -1046,7 +914,7 @@ case PCI_DEVICE_ID_CMD_643: #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { - hwif->XXX_udma = cmd64x_dmaproc; + hwif->udma_setup = cmd64x_udma_setup; hwif->udma_stop = cmd64x_udma_stop; hwif->udma_irq_status = cmd64x_udma_irq_status; } @@ -1059,10 +927,10 @@ #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { if (class_rev == 0x01) { - hwif->XXX_udma = cmd646_1_dmaproc; + hwif->udma_setup = cmd646_1_udma_setup; hwif->udma_stop = cmd646_1_udma_stop; } else { - hwif->XXX_udma = cmd64x_dmaproc; + hwif->udma_setup = cmd64x_udma_setup; hwif->udma_stop = cmd64x_udma_stop; hwif->udma_irq_status = cmd64x_udma_irq_status; } diff -Nru a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c --- a/drivers/ide/cs5530.c Sun Jun 2 18:44:58 2002 +++ b/drivers/ide/cs5530.c Sun Jun 2 18:44:58 2002 @@ -32,50 +32,6 @@ #include "ata-timing.h" #include "pcihost.h" -#undef DISPLAY_CS5530_TIMINGS - -#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int cs5530_get_info(char *, char **, off_t, int); -extern int (*cs5530_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - p += sprintf(p, "\n Cyrix 5530 Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer; -} -#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ - -byte cs5530_proc = 0; - /* * Set a new transfer mode at the drive */ @@ -235,7 +191,7 @@ return 0; } -int cs5530_dmaproc(struct ata_device *drive) +static int cs5530_udma_setup(struct ata_device *drive) { return cs5530_config_dma(drive); } @@ -250,14 +206,6 @@ unsigned short pcicmd = 0; unsigned long flags; -#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) - if (!cs5530_proc) { - cs5530_proc = 1; - bmide_dev = dev; - cs5530_display_info = &cs5530_get_info; - } -#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ - pci_for_each_dev (dev) { if (dev->vendor == PCI_VENDOR_ID_CYRIX) { switch (dev->device) { @@ -344,7 +292,7 @@ unsigned int basereg, d0_timings; #ifdef CONFIG_BLK_DEV_IDEDMA - hwif->XXX_udma = cs5530_dmaproc; + hwif->udma_setup = cs5530_udma_setup; hwif->highmem = 1; #else hwif->autodma = 0; @@ -374,7 +322,7 @@ init_chipset: pci_init_cs5530, init_channel: ide_init_cs5530, bootable: ON_BOARD, - flags: ATA_F_DMA | ATA_F_FDMA + flags: ATA_F_DMA }; int __init init_cs5530(void) diff -Nru a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c --- a/drivers/ide/cy82c693.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/cy82c693.c Sun Jun 2 18:44:56 2002 @@ -236,7 +236,7 @@ /* * used to set DMA mode for CY82C693 (single and multi modes) */ -static int cy82c693_dmaproc(struct ata_device *drive) +static int cy82c693_udma_setup(struct ata_device *drive) { /* * Set dma mode for drive everything else is done by the defaul func. @@ -443,7 +443,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { hwif->highmem = 1; - hwif->XXX_udma = cy82c693_dmaproc; + hwif->udma_setup = cy82c693_udma_setup; if (!noautodma) hwif->autodma = 1; } diff -Nru a/drivers/ide/device.c b/drivers/ide/device.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ide/device.c Sun Jun 2 18:44:58 2002 @@ -0,0 +1,162 @@ +/**** vi:set ts=8 sts=8 sw=8:************************************************ + * + * Copyright (C) 2002 Marcin Dalecki + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/* + * Common low leved device access code. This is the lowest layer of hardware + * access. + * + * This is the place where register set access portability will be handled in + * the future. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * Select a device for operation with possible busy waiting for the operation + * to complete. + */ +void ata_select(struct ata_device *drive, unsigned long delay) +{ + struct ata_channel *ch = drive->channel; + + if (!ch) + return; + + if (ch->selectproc) + ch->selectproc(drive); + OUT_BYTE(drive->select.all, ch->io_ports[IDE_SELECT_OFFSET]); + + /* The delays during probing for drives can be georgeous. Deal with + * it. + */ + if (delay) { + if (delay >= 1000) + mdelay(delay / 1000); + else + udelay(delay); + } +} + +EXPORT_SYMBOL(ata_select); + +/* + * Handle quirky routing of interrupts. + */ +void ata_mask(struct ata_device *drive) +{ + struct ata_channel *ch = drive->channel; + + if (!ch) + return; + + if (ch->maskproc) + ch->maskproc(drive); +} + +/* + * Check the state of the status register. + */ +int ata_status(struct ata_device *drive, u8 good, u8 bad) +{ + struct ata_channel *ch = drive->channel; + + drive->status = IN_BYTE(ch->io_ports[IDE_STATUS_OFFSET]); + + return (drive->status & (good | bad)) == good; +} + +EXPORT_SYMBOL(ata_status); + +/* + * Handle the nIEN - negated Interrupt ENable of the drive. + * This is controlling whatever the drive will acnowlenge commands + * with interrupts or not. + */ +int ata_irq_enable(struct ata_device *drive, int on) +{ + struct ata_channel *ch = drive->channel; + + if (!ch->io_ports[IDE_CONTROL_OFFSET]) + return 0; + + /* 0x08 is for legacy ATA-1 devices */ + if (on) + OUT_BYTE(0x08 | 0x00, ch->io_ports[IDE_CONTROL_OFFSET]); + else { + if (!ch->intrproc) + OUT_BYTE(0x08 | 0x02, ch->io_ports[IDE_CONTROL_OFFSET]); + else + ch->intrproc(drive); + } + + return 1; +} + +EXPORT_SYMBOL(ata_irq_enable); + +/* + * Perform a reset operation on the currently selected drive. + */ +void ata_reset(struct ata_channel *ch) +{ + unsigned long timeout = jiffies + WAIT_WORSTCASE; + u8 stat; + + if (!ch->io_ports[IDE_CONTROL_OFFSET]) + return; + + printk("%s: reset\n", ch->name); + /* 0x08 is for legacy ATA-1 devices */ + OUT_BYTE(0x08 | 0x04, ch->io_ports[IDE_CONTROL_OFFSET]); + udelay(10); + /* 0x08 is for legacy ATA-1 devices */ + OUT_BYTE(0x08 | 0x00, ch->io_ports[IDE_CONTROL_OFFSET]); + do { + mdelay(50); + stat = IN_BYTE(ch->io_ports[IDE_STATUS_OFFSET]); + } while ((stat & BUSY_STAT) && time_before(jiffies, timeout)); +} + +EXPORT_SYMBOL(ata_reset); + +/* + * Output a complete register file. + */ +void ata_out_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf) +{ + struct ata_channel *ch = drive->channel; + + OUT_BYTE(rf->feature, ch->io_ports[IDE_FEATURE_OFFSET]); + OUT_BYTE(rf->sector_count, ch->io_ports[IDE_NSECTOR_OFFSET]); + OUT_BYTE(rf->sector_number, ch->io_ports[IDE_SECTOR_OFFSET]); + OUT_BYTE(rf->low_cylinder, ch->io_ports[IDE_LCYL_OFFSET]); + OUT_BYTE(rf->high_cylinder, ch->io_ports[IDE_HCYL_OFFSET]); +} + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/ide/hd.c b/drivers/ide/hd.c --- a/drivers/ide/hd.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/hd.c Sun Jun 2 18:44:56 2002 @@ -66,6 +66,7 @@ static int revalidate_hddisk(kdev_t, int); +#define TIMEOUT_VALUE (6*HZ) #define HD_DELAY 0 #define MAX_ERRORS 16 /* Max read/write errors/sector */ @@ -110,20 +111,16 @@ static struct timer_list device_timer; -#define SET_TIMER \ +#define SET_TIMER \ do { \ mod_timer(&device_timer, jiffies + TIMEOUT_VALUE); \ } while (0) -#define CLEAR_TIMER del_timer(&device_timer); - -#undef SET_INTR - -#define SET_INTR(x) \ +#define SET_HANDLER(x) \ if ((DEVICE_INTR = (x)) != NULL) \ SET_TIMER; \ else \ - CLEAR_TIMER; + del_timer(&device_timer); #if (HD_DELAY > 0) @@ -279,7 +276,7 @@ reset = 1; return; } - SET_INTR(intr_addr); + SET_HANDLER(intr_addr); outb_p(hd_info[drive].ctl,HD_CMD); port=HD_DATA; outb_p(hd_info[drive].wpcom>>2,++port); @@ -429,7 +426,7 @@ if (CURRENT->current_nr_sectors <= 0) end_request(1); if (i > 0) { - SET_INTR(&read_intr); + SET_HANDLER(&read_intr); return; } (void) inb_p(HD_STATUS); @@ -467,7 +464,7 @@ if (!i || (CURRENT->bio && !SUBSECTOR(i))) end_request(1); if (i > 0) { - SET_INTR(&write_intr); + SET_HANDLER(&write_intr); outsw(HD_DATA,CURRENT->buffer,256); sti(); } else { @@ -833,7 +830,7 @@ printk("hd: unable to get major %d for hard disk\n",MAJOR_NR); return -1; } - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST, &hd_lock); + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock); blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255); add_gendisk(&hd_gendisk); init_timer(&device_timer); diff -Nru a/drivers/ide/hpt34x.c b/drivers/ide/hpt34x.c --- a/drivers/ide/hpt34x.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/hpt34x.c Sun Jun 2 18:44:56 2002 @@ -51,49 +51,6 @@ #define HPT343_DEBUG_DRIVE_INFO 0 -#undef DISPLAY_HPT34X_TIMINGS - -#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int hpt34x_get_info(char *, char **, off_t, int); -extern int (*hpt34x_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - p += sprintf(p, "\n HPT34X Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte hpt34x_proc = 0; - static void hpt34x_clear_chipset(struct ata_device *drive) { unsigned int reg1 = 0, tmp1 = 0; @@ -215,7 +172,7 @@ return !hpt34x_tune_chipset(drive, mode); } -static int config_drive_xfer_rate(struct ata_device *drive) +static int hpt34x_udma_setup(struct ata_device *drive) { struct hd_driveid *id = drive->id; int on = 1; @@ -289,49 +246,34 @@ return (dma_stat & 7) != 4; /* verify good DMA status */ } -static int do_udma(unsigned int reading, struct ata_device *drive, struct request *rq) +static int hpt34x_udma_init(struct ata_device *drive, struct request *rq) { struct ata_channel *ch = drive->channel; unsigned long dma_base = ch->dma_base; unsigned int count; + u8 cmd; if (!(count = udma_new_table(ch, rq))) return 1; /* try PIO instead of DMA */ - outl(ch->dmatable_dma, dma_base + 4); /* PRD table */ - reading |= 0x01; - outb(reading, dma_base); /* specify r/w */ + if (rq_data_dir(rq) == READ) + cmd = 0x09; + else + cmd = 0x01; + + outl(ch->dmatable_dma, dma_base + 4); /* PRD table */ + outb(cmd, dma_base); /* specify r/w */ outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ drive->waiting_for_dma = 1; if (drive->type != ATA_DISK) return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ - OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); + ide_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ + OUT_BYTE((cmd == 0x09) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); return 0; } - -static int hpt34x_udma_read(struct ata_device *drive, struct request *rq) -{ - return do_udma(1 << 3, drive, rq); -} - -static int hpt34x_udma_write(struct ata_device *drive, struct request *rq) -{ - return do_udma(0, drive, rq); -} - -/* - * This is specific to the HPT343 UDMA bios-less chipset - * and HPT345 UDMA bios chipset (stamped HPT363) - * by HighPoint|Triones Technologies, Inc. - */ -static int hpt34x_dmaproc(struct ata_device *drive) -{ - return config_drive_xfer_rate(drive); -} #endif /* @@ -380,14 +322,6 @@ __restore_flags(flags); /* local CPU only */ -#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) - if (!hpt34x_proc) { - hpt34x_proc = 1; - bmide_dev = dev; - hpt34x_display_info = &hpt34x_get_info; - } -#endif - return dev->irq; } @@ -407,9 +341,8 @@ hwif->autodma = 0; hwif->udma_stop = hpt34x_udma_stop; - hwif->udma_read = hpt34x_udma_read; - hwif->udma_write = hpt34x_udma_write; - hwif->XXX_udma = hpt34x_dmaproc; + hwif->udma_init = hpt34x_udma_init; + hwif->udma_setup = hpt34x_udma_setup; hwif->highmem = 1; } else { hwif->drives[0].autotune = 1; diff -Nru a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c --- a/drivers/ide/hpt366.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/hpt366.c Sun Jun 2 18:44:56 2002 @@ -68,18 +68,11 @@ #include "pcihost.h" -#undef DISPLAY_HPT366_TIMINGS - /* various tuning parameters */ #define HPT_RESET_STATE_ENGINE /*#define HPT_DELAY_INTERRUPT*/ /*#define HPT_SERIALIZE_IO*/ -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include -#endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ - static const char *quirk_drives[] = { "QUANTUM FIREBALLlct08 08", "QUANTUM FIREBALLP KA6.4", @@ -483,99 +476,8 @@ #define F_LOW_PCI_50 0x2d #define F_LOW_PCI_66 0x42 -static struct pci_dev *hpt_devs[HPT366_MAX_DEVS]; -static int n_hpt_devs; - static unsigned int hpt_min_rev(struct pci_dev *dev, int rev); -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) -static u8 hpt366_proc = 0; -static int hpt366_get_info(char *, char **, off_t, int); -extern int (*hpt366_display_info)(char *, char **, off_t, int); /* ide-proc.c */ - -static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - char *chipset_nums[] = {"366", "366", "368", - "370", "370A", "372", - "??", "374" }; - int i; - - p += sprintf(p, "\n " - "HighPoint HPT366/368/370/372/374\n"); - for (i = 0; i < n_hpt_devs; i++) { - struct pci_dev *dev = hpt_devs[i]; - unsigned short iobase = dev->resource[4].start; - u32 class_rev; - u8 c0, c1; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - - p += sprintf(p, "\nController: %d\n", i); - p += sprintf(p, "Chipset: HPT%s\n", - class_rev < sizeof(chipset_nums) / sizeof(char *) ? chipset_nums[class_rev] : "???"); - p += sprintf(p, "--------------- Primary Channel " - "--------------- Secondary Channel " - "--------------\n"); - - /* get the bus master status registers */ - c0 = inb_p(iobase + 0x2); - c1 = inb_p(iobase + 0xa); - p += sprintf(p, "Enabled: %s" - " %s\n", - (c0 & 0x80) ? "no" : "yes", - (c1 & 0x80) ? "no" : "yes"); - - if (hpt_min_rev(dev, 3)) { - u8 cbl; - cbl = inb_p(iobase + 0x7b); - outb_p(cbl | 1, iobase + 0x7b); - outb_p(cbl & ~1, iobase + 0x7b); - cbl = inb_p(iobase + 0x7a); - p += sprintf(p, "Cable: ATA-%d" - " ATA-%d\n", - (cbl & 0x02) ? 33 : 66, - (cbl & 0x01) ? 33 : 66); - p += sprintf(p, "\n"); - } - - p += sprintf(p, "--------------- drive0 --------- drive1 " - "------- drive0 ---------- drive1 -------\n"); - p += sprintf(p, "DMA capable: %s %s" - " %s %s\n", - (c0 & 0x20) ? "yes" : "no ", - (c0 & 0x40) ? "yes" : "no ", - (c1 & 0x20) ? "yes" : "no ", - (c1 & 0x40) ? "yes" : "no "); - - { - u8 c2, c3; - /* older revs don't have these registers mapped - * into io space */ - pci_read_config_byte(dev, 0x43, &c0); - pci_read_config_byte(dev, 0x47, &c1); - pci_read_config_byte(dev, 0x4b, &c2); - pci_read_config_byte(dev, 0x4f, &c3); - - p += sprintf(p, "Mode: %s %s" - " %s %s\n", - (c0 & 0x10) ? "UDMA" : (c0 & 0x20) ? "DMA " : - (c0 & 0x80) ? "PIO " : "off ", - (c1 & 0x10) ? "UDMA" : (c1 & 0x20) ? "DMA " : - (c1 & 0x80) ? "PIO " : "off ", - (c2 & 0x10) ? "UDMA" : (c2 & 0x20) ? "DMA " : - (c2 & 0x80) ? "PIO " : "off ", - (c3 & 0x10) ? "UDMA" : (c3 & 0x20) ? "DMA " : - (c3 & 0x80) ? "PIO " : "off "); - } - } - p += sprintf(p, "\n"); - - return p-buffer;/* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ - static int check_in_drive_lists(struct ata_device *drive, const char **list) { struct hd_driveid *id = drive->id; @@ -598,7 +500,7 @@ static unsigned int hpt_revision(struct pci_dev *dev) { - unsigned int class_rev; + u32 class_rev; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; @@ -654,7 +556,7 @@ } -static unsigned int pci_bus_clock_list(byte speed, struct chipset_bus_clock_list_entry * chipset_table) +static unsigned int pci_bus_clock_list(u8 speed, struct chipset_bus_clock_list_entry * chipset_table) { for ( ; chipset_table->xfer_speed ; chipset_table++) if (chipset_table->xfer_speed == speed) { @@ -663,18 +565,17 @@ return chipset_table->chipset_settings; } -static void hpt366_tune_chipset(struct ata_device *drive, byte speed) +static void hpt366_tune_chipset(struct ata_device *drive, u8 speed) { struct pci_dev *dev = drive->channel->pci_dev; - byte regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; - byte regfast = (drive->channel->unit) ? 0x55 : 0x51; + u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; + u8 regfast = (drive->channel->unit) ? 0x55 : 0x51; /* * since the channel is always 0 it does not matter. */ - unsigned int reg1 = 0; - unsigned int reg2 = 0; - byte drive_fast = 0; + u32 reg1, reg2; + u8 drive_fast; /* * Disable the "fast interrupt" prediction. @@ -699,19 +600,18 @@ pci_write_config_dword(dev, regtime, reg2); } -static void hpt368_tune_chipset(struct ata_device *drive, byte speed) +static void hpt368_tune_chipset(struct ata_device *drive, u8 speed) { hpt366_tune_chipset(drive, speed); } -static void hpt370_tune_chipset(struct ata_device *drive, byte speed) +static void hpt370_tune_chipset(struct ata_device *drive, u8 speed) { - byte regfast = (drive->channel->unit) ? 0x55 : 0x51; - unsigned int list_conf = 0; - unsigned int drive_conf = 0; - unsigned int conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; - byte drive_pci = 0x40 + (drive->dn * 4); - byte new_fast, drive_fast = 0; + u8 regfast = (drive->channel->unit) ? 0x55 : 0x51; + u32 list_conf, drive_conf; + u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; + u8 drive_pci = 0x40 + (drive->dn * 4); + u8 new_fast, drive_fast; struct pci_dev *dev = drive->channel->pci_dev; /* @@ -747,14 +647,13 @@ pci_write_config_dword(dev, drive_pci, list_conf); } -static void hpt372_tune_chipset(struct ata_device *drive, byte speed) +static void hpt372_tune_chipset(struct ata_device *drive, u8 speed) { - byte regfast = (drive->channel->unit) ? 0x55 : 0x51; - unsigned int list_conf = 0; - unsigned int drive_conf = 0; - unsigned int conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; - byte drive_pci = 0x40 + (drive->dn * 4); - byte drive_fast = 0; + u8 regfast = (drive->channel->unit) ? 0x55 : 0x51; + u32 list_conf, drive_conf; + u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; + u8 drive_pci = 0x40 + (drive->dn * 4); + u8 drive_fast; struct pci_dev *dev = drive->channel->pci_dev; /* @@ -775,12 +674,12 @@ pci_write_config_dword(dev, drive_pci, list_conf); } -static void hpt374_tune_chipset(struct ata_device *drive, byte speed) +static void hpt374_tune_chipset(struct ata_device *drive, u8 speed) { hpt372_tune_chipset(drive, speed); } -static int hpt3xx_tune_chipset(struct ata_device *drive, byte speed) +static int hpt3xx_tune_chipset(struct ata_device *drive, u8 speed) { struct pci_dev *dev = drive->channel->pci_dev; @@ -804,9 +703,9 @@ static void config_chipset_for_pio(struct ata_device *drive) { - unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; + static unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; unsigned short xfer_pio = drive->id->eide_pio_modes; - byte timing, speed, pio; + u8 timing, speed, pio; pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0; @@ -837,12 +736,12 @@ speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; break; } - (void) hpt3xx_tune_chipset(drive, speed); + hpt3xx_tune_chipset(drive, speed); } -static void hpt3xx_tune_drive(struct ata_device *drive, byte pio) +static void hpt3xx_tune_drive(struct ata_device *drive, u8 pio) { - byte speed; + u8 speed; switch(pio) { case 4: speed = XFER_PIO_4;break; case 3: speed = XFER_PIO_3;break; @@ -858,7 +757,7 @@ { struct pci_dev *dev = drive->channel->pci_dev; int map; - byte mode; + u8 mode; if (drive->type != ATA_DISK) return 0; @@ -914,34 +813,30 @@ if (drive->quirk_list) { /* drives in the quirk_list may not like intr setups/cleanups */ } else { - OUT_BYTE((drive)->ctl|2, drive->channel->io_ports[IDE_CONTROL_OFFSET]); + OUT_BYTE(0x02, drive->channel->io_ports[IDE_CONTROL_OFFSET]); } } -static void hpt3xx_maskproc(struct ata_device *drive, int mask) +static void hpt3xx_maskproc(struct ata_device *drive) { struct pci_dev *dev = drive->channel->pci_dev; + struct ata_channel *ch = drive->channel; if (drive->quirk_list) { if (hpt_min_rev(dev, 3)) { - byte reg5a = 0; + u8 reg5a; pci_read_config_byte(dev, 0x5a, ®5a); - if (((reg5a & 0x10) >> 4) != mask) - pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); - } else { - if (mask) { - disable_irq(drive->channel->irq); - } else { - enable_irq(drive->channel->irq); - } - } + if ((reg5a & 0x10) >> 4) + pci_write_config_byte(dev, 0x5a, reg5a & ~0x10); + } else + enable_irq(drive->channel->irq); } else { - if (IDE_CONTROL_REG) - OUT_BYTE(mask ? (drive->ctl | 2) : (drive->ctl & ~2), IDE_CONTROL_REG); + if (ch->io_ports[IDE_CONTROL_OFFSET]) + OUT_BYTE(0x00, ch->io_ports[IDE_CONTROL_OFFSET]); } } -static int config_drive_xfer_rate(struct ata_device *drive) +static int hpt3xx_udma_setup(struct ata_device *drive) { struct hd_driveid *id = drive->id; int on = 1; @@ -997,7 +892,7 @@ static void hpt366_udma_irq_lost(struct ata_device *drive) { - u8 reg50h = 0, reg52h = 0, reg5ah = 0; + u8 reg50h, reg52h, reg5ah; pci_read_config_byte(drive->channel->pci_dev, 0x50, ®50h); pci_read_config_byte(drive->channel->pci_dev, 0x52, ®52h); @@ -1008,15 +903,6 @@ pci_write_config_byte(drive->channel->pci_dev, 0x5a, reg5ah & ~0x10); } -/* - * This is specific to the HPT366 UDMA bios chipset - * by HighPoint|Triones Technologies, Inc. - */ -static int hpt366_dmaproc(struct ata_device *drive) -{ - return config_drive_xfer_rate(drive); -} - static void do_udma_start(struct ata_device *drive) { struct ata_channel *ch = drive->channel; @@ -1097,11 +983,6 @@ return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ } -static int hpt370_dmaproc(struct ata_device *drive) -{ - return config_drive_xfer_rate(drive); -} - static int hpt374_udma_stop(struct ata_device *drive) { struct ata_channel *ch = drive->channel; @@ -1124,11 +1005,6 @@ return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ } - -static int hpt374_dmaproc(struct ata_device *drive) -{ - return config_drive_xfer_rate(drive); -} #endif /* @@ -1140,8 +1016,8 @@ { #if 0 unsigned long high_16 = pci_resource_start(drive->channel->pci_dev, 4); - byte reset = (drive->channel->unit) ? 0x80 : 0x40; - byte reg59h = 0; + u8 reset = (drive->channel->unit) ? 0x80 : 0x40; + u8 reg59h; pci_read_config_byte(drive->channel->pci_dev, 0x59, ®59h); pci_write_config_byte(drive->channel->pci_dev, 0x59, reg59h|reset); @@ -1154,10 +1030,9 @@ { struct ata_channel *ch = drive->channel; struct pci_dev *dev = ch->pci_dev; - byte reset = (ch->unit) ? 0x80 : 0x40; - byte state_reg = (ch->unit) ? 0x57 : 0x53; - byte reg59h = 0; - byte regXXh = 0; + u8 reset = (ch->unit) ? 0x80 : 0x40; + u8 state_reg = (ch->unit) ? 0x57 : 0x53; + u8 reg59h, regXXh; if (!ch) return -EINVAL; @@ -1366,8 +1241,8 @@ static void __init hpt366_init(struct pci_dev *dev) { - unsigned int reg1 = 0; - u8 drive_fast = 0; + u32 reg1; + u8 drive_fast; /* * Disable the "fast interrupt" prediction. @@ -1394,7 +1269,7 @@ static unsigned int __init hpt366_init_chipset(struct pci_dev *dev) { - u8 test = 0; + u8 test; if (dev->resource[PCI_ROM_RESOURCE].start) pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); @@ -1420,23 +1295,13 @@ else hpt366_init(dev); - if (n_hpt_devs < HPT366_MAX_DEVS) - hpt_devs[n_hpt_devs++] = dev; - -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) - if (!hpt366_proc) { - hpt366_proc = 1; - hpt366_display_info = &hpt366_get_info; - } -#endif - return dev->irq; } static unsigned int __init hpt366_ata66_check(struct ata_channel *ch) { - u8 ata66 = 0; - u8 regmask = (ch->unit) ? 0x01 : 0x02; + u8 ata66; + u8 regmask = (ch->unit) ? 0x01 : 0x02; pci_read_config_byte(ch->pci_dev, 0x5a, &ata66); #ifdef DEBUG @@ -1466,7 +1331,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA if (ch->dma_base) { if (hpt_min_rev(dev, 3)) { - byte reg5ah = 0; + u8 reg5ah; pci_read_config_byte(dev, 0x5a, ®5ah); if (reg5ah & 0x10) /* interrupt force enable */ pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); @@ -1480,27 +1345,27 @@ if (hpt_min_rev(dev, 7)) { ch->udma_stop = hpt374_udma_stop; - ch->XXX_udma = hpt374_dmaproc; + ch->udma_setup = hpt3xx_udma_setup; } else if (hpt_min_rev(dev, 5)) { ch->udma_stop = hpt374_udma_stop; - ch->XXX_udma = hpt374_dmaproc; + ch->udma_setup = hpt3xx_udma_setup; } else if (hpt_min_rev(dev, 3)) { ch->udma_start = hpt370_udma_start; ch->udma_stop = hpt370_udma_stop; ch->udma_timeout = hpt370_udma_timeout; ch->udma_irq_lost = hpt370_udma_irq_lost; - ch->XXX_udma = hpt370_dmaproc; + ch->udma_setup = hpt3xx_udma_setup; } } else if (hpt_min_rev(dev, 2)) { ch->udma_irq_lost = hpt366_udma_irq_lost; // ch->resetproc = hpt3xx_reset; // ch->busproc = hpt3xx_tristate; - ch->XXX_udma = hpt366_dmaproc; + ch->udma_setup = hpt3xx_udma_setup; } else { ch->udma_irq_lost = hpt366_udma_irq_lost; // ch->resetproc = hpt3xx_reset; // ch->busproc = hpt3xx_tristate; - ch->XXX_udma = hpt366_dmaproc; + ch->udma_setup = hpt3xx_udma_setup; } if (!noautodma) ch->autodma = 1; @@ -1521,14 +1386,12 @@ static void __init hpt366_init_dma(struct ata_channel *ch, unsigned long dmabase) { - u8 masterdma = 0; - u8 slavedma = 0; - u8 dma_new = 0; - u8 dma_old = inb(dmabase+2); - u8 primary = ch->unit ? 0x4b : 0x43; - u8 secondary = ch->unit ? 0x4f : 0x47; + u8 masterdma, slavedma; + u8 dma_old = inb(dmabase + 2); + u8 dma_new = dma_old; + u8 primary = ch->unit ? 0x4b : 0x43; + u8 secondary = primary + 4; - dma_new = dma_old; pci_read_config_byte(ch->pci_dev, primary, &masterdma); pci_read_config_byte(ch->pci_dev, secondary, &slavedma); @@ -1588,5 +1451,5 @@ ata_register_chipset(&chipsets[i]); } - return 0; + return 0; } diff -Nru a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c --- a/drivers/ide/ht6560b.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/ht6560b.c Sun Jun 2 18:44:56 2002 @@ -123,16 +123,16 @@ static void ht6560b_selectproc(struct ata_device *drive) { unsigned long flags; - static byte current_select = 0; - static byte current_timing = 0; - byte select, timing; - + static u8 current_select = 0; + static u8 current_timing = 0; + u8 select, timing; + __save_flags (flags); /* local CPU only */ __cli(); /* local CPU only */ - + select = HT_CONFIG(drive); timing = HT_TIMING(drive); - + if (select != current_select || timing != current_timing) { current_select = select; current_timing = timing; @@ -147,7 +147,7 @@ * Set timing for this drive: */ outb(timing, IDE_SELECT_REG); - (void) inb(IDE_STATUS_REG); + ata_status(drive, 0, 0); #ifdef DEBUG printk("ht6560b: %s: select=%#x timing=%#x\n", drive->name, select, timing); #endif @@ -160,13 +160,13 @@ */ static int __init try_to_init_ht6560b(void) { - byte orig_value; + u8 orig_value; int i; - + /* Autodetect ht6560b */ if ((orig_value=inb(HT_CONFIG_PORT)) == 0xff) return 0; - + for (i=3;i>0;i--) { outb(0x00, HT_CONFIG_PORT); if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) { @@ -183,9 +183,9 @@ * Ht6560b autodetected */ outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT); - outb(HT_TIMING_DEFAULT, 0x1f6); /* IDE_SELECT_REG */ - (void) inb(0x1f7); /* IDE_STATUS_REG */ - + outb(HT_TIMING_DEFAULT, 0x1f6); /* SELECT */ + (void) inb(0x1f7); /* STATUS */ + printk("\nht6560b " HT6560B_VERSION ": chipset detected and initialized" #ifdef DEBUG @@ -228,19 +228,19 @@ if (recovery_cycles < 2) recovery_cycles = 2; if (active_cycles > 15) active_cycles = 15; if (recovery_cycles > 15) recovery_cycles = 0; /* 0==16 */ - + #ifdef DEBUG printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)\n", drive->name, pio - XFER_PIO_0, recovery_cycles, recovery_time, active_cycles, active_time); #endif - + return (byte)((recovery_cycles << 4) | active_cycles); } else { - + #ifdef DEBUG printk("ht6560b: drive %s setting pio=0\n", drive->name); #endif - + return HT_TIMING_DEFAULT; /* default setting */ } } @@ -252,10 +252,10 @@ { unsigned long flags; int t = HT_PREFETCH_MODE << 8; - + save_flags (flags); /* all CPUs */ cli(); /* all CPUs */ - + /* * Prefetch mode and unmask irq seems to conflict */ @@ -267,9 +267,9 @@ drive->drive_data &= ~t; /* disable prefetch mode */ drive->channel->no_unmask = 0; } - + restore_flags (flags); /* all CPUs */ - + #ifdef DEBUG printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis")); #endif @@ -279,24 +279,24 @@ { unsigned long flags; byte timing; - + switch (pio) { case 8: /* set prefetch off */ case 9: /* set prefetch on */ ht_set_prefetch(drive, pio & 1); return; } - + timing = ht_pio2timings(drive, pio); - + save_flags (flags); /* all CPUs */ cli(); /* all CPUs */ - + drive->drive_data &= 0xff00; drive->drive_data |= timing; - + restore_flags (flags); /* all CPUs */ - + #ifdef DEBUG printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing); #endif @@ -305,7 +305,7 @@ void __init init_ht6560b (void) { int t; - + if (check_region(HT_CONFIG_PORT,1)) { printk(KERN_ERR "ht6560b: PORT %#x ALREADY IN USE\n", HT_CONFIG_PORT); } else { diff -Nru a/drivers/ide/icside.c b/drivers/ide/icside.c --- a/drivers/ide/icside.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/icside.c Sun Jun 2 18:44:56 2002 @@ -232,8 +232,9 @@ * Handle routing of interrupts. This is called before * we write the command to the drive. */ -static void icside_maskproc(struct ata_device *drive, int mask) +static void icside_maskproc(struct ata_device *drive) { + const int mask = 0; struct ata_channel *ch = drive->channel; struct icside_state *state = ch->hw.priv; unsigned long flags; @@ -465,12 +466,9 @@ static ide_startstop_t icside_dmaintr(struct ata_device *drive, struct request *rq) { int dma_stat; - byte stat; dma_stat = icside_dma_stop(drive); - - stat = GET_STAT(); /* get drive status */ - if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { + if (ata_status(drive, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) { if (!dma_stat) { __ide_end_request(drive, rq, 1, rq->nr_sectors); return ide_stopped; @@ -478,7 +476,7 @@ printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); } - return ide_error(drive, rq, "dma_intr", stat); + return ata_error(drive, rq, __FUNCTION__); } static int @@ -546,7 +544,7 @@ return 0; } -static int icside_dma_write(struct ata_device *drive, struct request *rq) +static int icside_dma_init(struct ata_device *drive, struct request *rq) { struct ata_channel *ch = drive->channel; unsigned int cmd; @@ -587,7 +585,8 @@ static void icside_dma_timeout(struct ata_device *drive) { printk(KERN_ERR "ATA: %s: UDMA timeout occured:", drive->name); - ide_dump_status(drive, NULL, "UDMA timeout", GET_STAT()); + ata_status(drive, 0, 0); + ide_dump_status(drive, NULL, "UDMA timeout", drive->status); } static void icside_irq_lost(struct ata_device *drive) @@ -613,12 +612,11 @@ ch->dmatable_cpu = NULL; ch->dmatable_dma = 0; ch->speedproc = icside_set_speed; - ch->XXX_udma = icside_dma_check; + ch->udma_setup = icside_dma_check; ch->udma_enable = icside_dma_enable; ch->udma_start = icside_dma_start; ch->udma_stop = icside_dma_stop; - ch->udma_read = icside_dma_read; - ch->udma_write = icside_dma_write; + ch->udma_init = icside_dma_init; ch->udma_irq_status = icside_irq_status; ch->udma_timeout = icside_dma_timeout; ch->udma_irq_lost = icside_irq_lost; diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c --- a/drivers/ide/ide-cd.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ide/ide-cd.c Sun Jun 2 18:44:57 2002 @@ -535,7 +535,7 @@ /* stuff the sense request in front of our current request */ rq = &info->request_sense_request; - ide_init_drive_cmd(rq); + memset(rq, 0, sizeof(*rq)); rq->cmd[0] = GPCMD_REQUEST_SENSE; rq->cmd[4] = pc->buflen; rq->flags = REQ_SENSE; @@ -565,14 +565,14 @@ static int cdrom_decode_status(ide_startstop_t *startstop, struct ata_device *drive, struct request *rq, int good_stat, int *stat_ret) { - int stat, err, sense_key; + int err, sense_key; struct packet_command *pc; + int ok; /* Check for errors. */ - stat = GET_STAT(); - *stat_ret = stat; - - if (OK_STAT (stat, good_stat, BAD_R_STAT)) + ok = ata_status(drive, good_stat, BAD_R_STAT); + *stat_ret = drive->status; + if (ok) return 0; /* Get the IDE error register. */ @@ -594,7 +594,7 @@ pc = (struct packet_command *) rq->special; pc->stat = 1; cdrom_end_request(drive, rq, 1); - *startstop = ide_error (drive, rq, "request sense failure", stat); + *startstop = ata_error(drive, rq, "request sense failure"); return 1; } else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) { @@ -614,7 +614,7 @@ return 0; } else if (!pc->quiet) { /* Otherwise, print an error. */ - ide_dump_status(drive, rq, "packet command error", stat); + ide_dump_status(drive, rq, "packet command error", drive->status); } /* Set the error flag and complete the request. @@ -625,7 +625,7 @@ the semaphore from the packet command request to the request sense request. */ - if ((stat & ERR_STAT) != 0) { + if (drive->status & ERR_STAT) { wait = rq->waiting; rq->waiting = NULL; } @@ -637,7 +637,7 @@ * Think hard about how to get rid of it... */ - if ((stat & ERR_STAT) != 0) + if (drive->status & ERR_STAT) cdrom_queue_request_sense(drive, wait, pc->sense, pc); } else if (rq->flags & REQ_CMD) { /* Handle errors from READ and WRITE requests. */ @@ -662,18 +662,18 @@ sense_key == DATA_PROTECT) { /* No point in retrying after an illegal request or data protect error.*/ - ide_dump_status(drive, rq, "command error", stat); + ide_dump_status(drive, rq, "command error", drive->status); cdrom_end_request(drive, rq, 0); } else if (sense_key == MEDIUM_ERROR) { /* No point in re-trying a zillion times on a bad * sector. The error is not correctable at all. */ - ide_dump_status(drive, rq, "media error (bad sector)", stat); + ide_dump_status(drive, rq, "media error (bad sector)", drive->status); cdrom_end_request(drive, rq, 0); } else if ((err & ~ABRT_ERR) != 0) { /* Go to the default handler for other errors. */ - *startstop = ide_error(drive, rq, __FUNCTION__, stat); + *startstop = ata_error(drive, rq, __FUNCTION__); return 1; } else if ((++rq->errors > ERROR_MAX)) { /* We've racked up too many retries. Abort. */ @@ -682,7 +682,7 @@ /* If we got a CHECK_CONDITION status, queue a request sense command. */ - if ((stat & ERR_STAT) != 0) + if (drive->status & ERR_STAT) cdrom_queue_request_sense(drive, NULL, NULL, NULL); } else blk_dump_rq_flags(rq, "ide-cd bad flags"); @@ -736,10 +736,8 @@ return startstop; if (info->dma) { - if (info->cmd == READ) - info->dma = !udma_read(drive, rq); - else if (info->cmd == WRITE) - info->dma = !udma_write(drive, rq); + if (info->cmd == READ || info->cmd == WRITE) + info->dma = !udma_init(drive, rq); else printk("ide-cd: DMA set, but not allowed\n"); } @@ -751,9 +749,7 @@ OUT_BYTE(xferlen & 0xff, IDE_LCYL_REG); OUT_BYTE(xferlen >> 8 , IDE_HCYL_REG); - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl, IDE_CONTROL_REG); - + ata_irq_enable(drive, 1); if (info->dma) udma_start(drive, rq); @@ -880,7 +876,7 @@ /* Some drives (ASUS) seem to tell us that status * info is available. just get it and ignore. */ - GET_STAT(); + ata_status(drive, 0, 0); return 0; } else { /* Drive wants a command packet, or invalid ireason... */ @@ -918,7 +914,7 @@ __ide_end_request(drive, rq, 1, rq->nr_sectors); return ide_stopped; } else - return ide_error (drive, rq, "dma error", stat); + return ata_error(drive, rq, "dma error"); } /* Read the interrupt reason and the transfer length. */ @@ -1391,9 +1387,8 @@ /* Start of retry loop. */ do { - ide_init_drive_cmd(&rq); + memset(&rq, 0, sizeof(rq)); memcpy(rq.cmd, cmd, CDROM_PACKET_SIZE); - rq.flags = REQ_PC; /* FIXME --mdcki */ @@ -1498,7 +1493,7 @@ */ if (dma) { if (dma_error) - return ide_error(drive, rq, "dma error", stat); + return ata_error(drive, rq, "dma error"); __ide_end_request(drive, rq, 1, rq->nr_sectors); return ide_stopped; @@ -1619,9 +1614,8 @@ if (rq->flags & REQ_CMD) { if (CDROM_CONFIG_FLAGS(drive)->seeking) { unsigned long elpased = jiffies - info->start_seek; - int stat = GET_STAT(); - if ((stat & SEEK_STAT) != SEEK_STAT) { + if (!ata_status(drive, SEEK_STAT, 0)) { if (elpased < IDECD_SEEK_TIMEOUT) { ide_stall_queue(drive, IDECD_SEEK_TIMER); return ide_stopped; @@ -2279,7 +2273,7 @@ struct request req; int ret; - ide_init_drive_cmd(&req); + memset(&req, 0, sizeof(req)); req.flags = REQ_SPECIAL; ret = ide_do_drive_cmd(drive, &req, ide_wait); diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/ide-disk.c Sun Jun 2 18:44:56 2002 @@ -170,7 +170,7 @@ args.taskfile.device_head = head; args.taskfile.device_head |= drive->select.all; - args.taskfile.command = get_command(drive, rq_data_dir(rq)); + args.cmd = get_command(drive, rq_data_dir(rq)); #ifdef DEBUG printk("%s: %sing: ", drive->name, @@ -211,7 +211,7 @@ args.taskfile.device_head = ((block >> 8) & 0x0f); args.taskfile.device_head |= drive->select.all; - args.taskfile.command = get_command(drive, rq_data_dir(rq)); + args.cmd = get_command(drive, rq_data_dir(rq)); #ifdef DEBUG printk("%s: %sing: ", drive->name, @@ -257,15 +257,14 @@ args.taskfile.sector_number = block; /* low lba */ args.taskfile.low_cylinder = (block >>= 8); /* mid lba */ args.taskfile.high_cylinder = (block >>= 8); /* hi lba */ + args.taskfile.device_head = drive->select.all; args.hobfile.sector_number = (block >>= 8); /* low lba */ args.hobfile.low_cylinder = (block >>= 8); /* mid lba */ args.hobfile.high_cylinder = (block >>= 8); /* hi lba */ + args.hobfile.device_head = drive->select.all; - args.taskfile.device_head = drive->select.all; - args.hobfile.device_head = args.taskfile.device_head; - args.hobfile.control = (drive->ctl|0x80); - args.taskfile.command = get_command(drive, rq_data_dir(rq)); + args.cmd = get_command(drive, rq_data_dir(rq)); #ifdef DEBUG printk("%s: %sing: ", drive->name, @@ -356,7 +355,7 @@ memset(&args, 0, sizeof(args)); - args.taskfile.command = WIN_DOORLOCK; + args.cmd = WIN_DOORLOCK; ide_cmd_type_parser(&args); /* @@ -378,9 +377,9 @@ memset(&args, 0, sizeof(args)); if (drive->id->cfs_enable_2 & 0x2400) - args.taskfile.command = WIN_FLUSH_CACHE_EXT; + args.cmd = WIN_FLUSH_CACHE_EXT; else - args.taskfile.command = WIN_FLUSH_CACHE; + args.cmd = WIN_FLUSH_CACHE; ide_cmd_type_parser(&args); @@ -396,7 +395,7 @@ invalidate_bdev(inode->i_bdev, 0); memset(&args, 0, sizeof(args)); - args.taskfile.command = WIN_DOORUNLOCK; + args.cmd = WIN_DOORUNLOCK; ide_cmd_type_parser(&args); if (drive->doorlocking && @@ -445,7 +444,7 @@ memset(&args, 0, sizeof(args)); args.taskfile.sector_count = arg; - args.taskfile.command = WIN_SETMULT; + args.cmd = WIN_SETMULT; ide_cmd_type_parser(&args); if (!ide_raw_taskfile(drive, &args)) { @@ -476,7 +475,7 @@ memset(&args, 0, sizeof(args)); args.taskfile.feature = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; - args.taskfile.command = WIN_SETFEATURES; + args.cmd = WIN_SETFEATURES; ide_cmd_type_parser(&args); ide_raw_taskfile(drive, &args); @@ -490,7 +489,7 @@ struct ata_taskfile args; memset(&args, 0, sizeof(args)); - args.taskfile.command = WIN_STANDBYNOW1; + args.cmd = WIN_STANDBYNOW1; ide_cmd_type_parser(&args); return ide_raw_taskfile(drive, &args); @@ -503,7 +502,7 @@ memset(&args, 0, sizeof(args)); args.taskfile.feature = (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM; args.taskfile.sector_count = arg; - args.taskfile.command = WIN_SETFEATURES; + args.cmd = WIN_SETFEATURES; ide_cmd_type_parser(&args); ide_raw_taskfile(drive, &args); @@ -518,7 +517,7 @@ if (!drive->driver) return -EPERM; - if (!drive->channel->XXX_udma) + if (!drive->channel->udma_setup) return -EPERM; if (arg == drive->queue_depth && drive->using_tcq) @@ -623,14 +622,14 @@ /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(args)); args.taskfile.device_head = 0x40; - args.taskfile.command = WIN_READ_NATIVE_MAX; + args.cmd = WIN_READ_NATIVE_MAX; args.handler = task_no_data_intr; /* submit command request */ ide_raw_taskfile(drive, &args); /* if OK, compute maximum address value */ - if ((args.taskfile.command & 0x01) == 0) { + if (!(drive->status & ERR_STAT)) { addr = ((args.taskfile.device_head & 0x0f) << 24) | (args.taskfile.high_cylinder << 16) | (args.taskfile.low_cylinder << 8) @@ -651,14 +650,14 @@ memset(&args, 0, sizeof(args)); args.taskfile.device_head = 0x40; - args.taskfile.command = WIN_READ_NATIVE_MAX_EXT; + args.cmd = WIN_READ_NATIVE_MAX_EXT; args.handler = task_no_data_intr; /* submit command request */ ide_raw_taskfile(drive, &args); /* if OK, compute maximum address value */ - if ((args.taskfile.command & 0x01) == 0) { + if (!(drive->status & ERR_STAT)) { u32 high = (args.hobfile.high_cylinder << 16) | (args.hobfile.low_cylinder << 8) | args.hobfile.sector_number; @@ -692,12 +691,12 @@ args.taskfile.high_cylinder = (addr_req >> 16); args.taskfile.device_head = ((addr_req >> 24) & 0x0f) | 0x40; - args.taskfile.command = WIN_SET_MAX; + args.cmd = WIN_SET_MAX; args.handler = task_no_data_intr; /* submit command request */ ide_raw_taskfile(drive, &args); /* if OK, read new maximum address value */ - if ((args.taskfile.command & 0x01) == 0) { + if (!(drive->status & ERR_STAT)) { addr_set = ((args.taskfile.device_head & 0x0f) << 24) | (args.taskfile.high_cylinder << 16) | (args.taskfile.low_cylinder << 8) @@ -720,20 +719,19 @@ args.taskfile.low_cylinder = (addr_req >>= 8); args.taskfile.high_cylinder = (addr_req >>= 8); args.taskfile.device_head = 0x40; - args.taskfile.command = WIN_SET_MAX_EXT; + args.cmd = WIN_SET_MAX_EXT; args.hobfile.sector_number = (addr_req >>= 8); args.hobfile.low_cylinder = (addr_req >>= 8); args.hobfile.high_cylinder = (addr_req >>= 8); args.hobfile.device_head = 0x40; - args.hobfile.control = (drive->ctl | 0x80); args.handler = task_no_data_intr; /* submit command request */ ide_raw_taskfile(drive, &args); /* if OK, compute maximum address value */ - if ((args.taskfile.command & 0x01) == 0) { + if (!(drive->status & ERR_STAT)) { u32 high = (args.hobfile.high_cylinder << 16) | (args.hobfile.low_cylinder << 8) | args.hobfile.sector_number; diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c --- a/drivers/ide/ide-floppy.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/ide-floppy.c Sun Jun 2 18:44:56 2002 @@ -134,17 +134,6 @@ #define IDEFLOPPY_PC_STACK (10 + IDEFLOPPY_MAX_PC_RETRIES) /* - * Packet command flag bits. - */ -#define PC_ABORT 0 /* Set when an error is considered normal - We won't retry */ -#define PC_DMA_RECOMMENDED 2 /* 1 when we prefer to use DMA if possible */ -#define PC_DMA_IN_PROGRESS 3 /* 1 while DMA in progress */ -#define PC_DMA_ERROR 4 /* 1 when encountered problem during DMA */ -#define PC_WRITING 5 /* Data direction */ - -#define PC_SUPPRESS_ERROR 6 /* Suppress error reporting */ - -/* * Removable Block Access Capabilities Page */ typedef struct { @@ -631,7 +620,7 @@ #if IDEFLOPPY_DEBUG_LOG printk (KERN_INFO "Reached idefloppy_end_request\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ +#endif switch (uptodate) { case 0: error = IDEFLOPPY_ERROR_GENERAL; break; @@ -643,12 +632,16 @@ /* Why does this happen? */ if (!rq) return 0; + if (!(rq->flags & IDEFLOPPY_RQ)) { ide_end_request(drive, rq, uptodate); return 0; } + rq->errors = error; - ide_end_drive_cmd (drive, rq, 0, 0); + blkdev_dequeue_request(rq); + drive->rq = NULL; + end_that_request_last(rq); return 0; } @@ -723,10 +716,10 @@ static void idefloppy_queue_pc_head(struct ata_device *drive, struct atapi_packet_command *pc, struct request *rq) { - ide_init_drive_cmd (rq); + memset(rq, 0, sizeof(*rq)); + rq->flags = IDEFLOPPY_RQ; /* FIXME: --mdcki */ rq->buffer = (char *) pc; - rq->flags = IDEFLOPPY_RQ; (void) ide_do_drive_cmd (drive, rq, ide_preempt); } @@ -855,7 +848,8 @@ } #endif - status.all = GET_STAT(); /* Clear the interrupt */ + ata_status(drive, 0, 0); + status.all = drive->status; /* Clear the interrupt */ if (!status.b.drq) { /* No more interrupts */ #if IDEFLOPPY_DEBUG_LOG @@ -1066,20 +1060,15 @@ if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) udma_enable(drive, 0, 1); - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) { - if (test_bit (PC_WRITING, &pc->flags)) - dma_ok = !udma_write(drive, rq); - else - dma_ok = !udma_read(drive, rq); - } + if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) + dma_ok = !udma_init(drive, rq); #endif - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl,IDE_CONTROL_REG); - OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG); - OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG); - OUT_BYTE (drive->select.all,IDE_SELECT_REG); + ata_irq_enable(drive, 1); + OUT_BYTE(dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ + OUT_BYTE(bcount.b.high,IDE_BCOUNTH_REG); + OUT_BYTE(bcount.b.low,IDE_BCOUNTL_REG); + OUT_BYTE(drive->select.all,IDE_SELECT_REG); #ifdef CONFIG_BLK_DEV_IDEDMA if (dma_ok) { /* Begin DMA, if necessary */ @@ -1282,11 +1271,12 @@ { struct request rq; - ide_init_drive_cmd (&rq); + memset(&rq, 0, sizeof(rq)); /* FIXME: --mdcki */ rq.buffer = (char *) pc; rq.flags = IDEFLOPPY_RQ; - return ide_do_drive_cmd (drive, &rq, ide_wait); + + return ide_do_drive_cmd(drive, &rq, ide_wait); } /* @@ -1599,7 +1589,8 @@ __save_flags(flags); __cli(); - status.all=GET_STAT(); + ata_status(drive, 0, 0); + status.all = drive->status; __restore_flags(flags); progress_indication= !status.b.dsc ? 0:0x10000; diff -Nru a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c --- a/drivers/ide/ide-pci.c Sun Jun 2 18:44:58 2002 +++ b/drivers/ide/ide-pci.c Sun Jun 2 18:44:58 2002 @@ -168,8 +168,7 @@ int port, u8 class_rev, int pciirq, - int autodma, - unsigned short *pcicmd) + int autodma) { unsigned long base = 0; unsigned long dma_base; @@ -319,23 +318,12 @@ goto no_dma; } - if (!(*pcicmd & PCI_COMMAND_MASTER)) { - /* - * Set up BM-DMA capability (PnP BIOS should have done this - * already). Default to DMA off on the drive, if we had to - * configure it here. This should most propably be enabled no - * all chipsets which can be expected to be used on systems - * without a BIOS equivalent. - */ - if (!(d->flags | ATA_F_FDMA)) - ch->autodma = 0; - pci_write_config_word(dev, PCI_COMMAND, *pcicmd | PCI_COMMAND_MASTER); - if (pci_read_config_word(dev, PCI_COMMAND, pcicmd) || !(*pcicmd & PCI_COMMAND_MASTER)) { - printk("%s: %s error updating PCICMD\n", - ch->name, dev->name); - dma_base = 0; - } - } + + /* The function below will check itself whatever there is something to + * be done or not. We don't have therefore to care whatever it was + * already enabled by the primary channel run. + */ + pci_set_master(dev); if (d->init_dma) d->init_dma(ch, dma_base); else @@ -472,8 +460,8 @@ /* * Set up IDE chanells. First the primary, then the secondary. */ - setup_host_channel(dev, d, ATA_PRIMARY, class_rev, pciirq, autodma, &pcicmd); - setup_host_channel(dev, d, ATA_SECONDARY, class_rev, pciirq, autodma, &pcicmd); + setup_host_channel(dev, d, ATA_PRIMARY, class_rev, pciirq, autodma); + setup_host_channel(dev, d, ATA_SECONDARY, class_rev, pciirq, autodma); } /* diff -Nru a/drivers/ide/ide-pmac.c b/drivers/ide/ide-pmac.c --- a/drivers/ide/ide-pmac.c Sun Jun 2 18:44:58 2002 +++ b/drivers/ide/ide-pmac.c Sun Jun 2 18:44:58 2002 @@ -260,11 +260,9 @@ static void pmac_udma_enable(struct ata_device *drive, int on, int verbose); static int pmac_udma_start(struct ata_device *drive, struct request *rq); static int pmac_udma_stop(struct ata_device *drive); -static int pmac_do_udma(unsigned int reading, struct ata_device *drive, struct request *rq); -static int pmac_udma_read(struct ata_device *drive, struct request *rq); -static int pmac_udma_write(struct ata_device *drive, struct request *rq); +static int pmac_udma_init(struct ata_device *drive, struct request *rq); static int pmac_udma_irq_status(struct ata_device *drive); -static int pmac_ide_dmaproc(struct ata_device *drive); +static int pmac_udma_setup(struct ata_device *drive); static int pmac_ide_build_dmatable(struct ata_device *drive, struct request *rq, int ix, int wr); static int pmac_ide_tune_chipset(struct ata_device *drive, byte speed); static void pmac_ide_tuneproc(struct ata_device *drive, byte pio); @@ -334,10 +332,9 @@ ide_hwifs[ix].udma_enable = pmac_udma_enable; ide_hwifs[ix].udma_start = pmac_udma_start; ide_hwifs[ix].udma_stop = pmac_udma_stop; - ide_hwifs[ix].udma_read = pmac_udma_read; - ide_hwifs[ix].udma_write = pmac_udma_write; + ide_hwifs[ix].udma_init = pmac_udma_init; ide_hwifs[ix].udma_irq_status = pmac_udma_irq_status; - ide_hwifs[ix].XXX_udma = pmac_ide_dmaproc; + ide_hwifs[ix].udma_setup = pmac_udma_setup; #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO if (!noautodma) ide_hwifs[ix].autodma = 1; @@ -395,21 +392,21 @@ { /* Timeout bumped for some powerbooks */ int timeout = 2000; - byte stat; - while(--timeout) { - stat = GET_STAT(); - if(!(stat & BUSY_STAT)) { + while (--timeout) { + if(ata_status(drive, 0, BUSY_STAT)) { if (drive->ready_stat == 0) break; - else if((stat & drive->ready_stat) || (stat & ERR_STAT)) + else if((drive->status & drive->ready_stat) + || (drive->status & ERR_STAT)) break; } mdelay(1); } - if((stat & ERR_STAT) || timeout <= 0) { - if (stat & ERR_STAT) { - printk(KERN_ERR "ide_pmac: wait_for_ready, error status: %x\n", stat); + if((drive->status & ERR_STAT) || timeout <= 0) { + if (drive->status & ERR_STAT) { + printk(KERN_ERR "ide_pmac: wait_for_ready, error status: %x\n", + drive->status); } return 1; } @@ -417,7 +414,7 @@ } static int __pmac -pmac_ide_do_setfeature(struct ata_device *drive, byte command) +pmac_ide_do_setfeature(struct ata_device *drive, u8 command) { int result = 1; unsigned long flags; @@ -425,16 +422,16 @@ disable_irq(hwif->irq); /* disable_irq_nosync ?? */ udelay(1); - SELECT_DRIVE(drive->channel, drive); - SELECT_MASK(drive->channel, drive, 0); + ata_select(drive, 0); + ata_mask(drive); udelay(1); - (void)GET_STAT(); /* Get rid of pending error state */ - if(wait_for_ready(drive)) { + ata_status(drive, 0, 0); /* Get rid of pending error state */ + if (wait_for_ready(drive)) { printk(KERN_ERR "pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n"); goto out; } udelay(10); - OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); + ata_irq_enable(drive, 0); OUT_BYTE(command, IDE_NSECTOR_REG); OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); @@ -443,11 +440,11 @@ ide__sti(); /* local CPU only -- for jiffies */ result = wait_for_ready(drive); __restore_flags(flags); /* local CPU only */ - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); + ata_irq_enable(drive, 1); if (result) printk(KERN_ERR "pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n"); out: - SELECT_MASK(drive->channel, drive, 0); + ata_mask(drive); if (result == 0) { drive->id->dma_ultra &= ~0xFF00; drive->id->dma_mword &= ~0x0F00; @@ -1043,10 +1040,9 @@ ide_hwifs[ix].udma_enable = pmac_udma_enable; ide_hwifs[ix].udma_start = pmac_udma_start; ide_hwifs[ix].udma_stop = pmac_udma_stop; - ide_hwifs[ix].udma_read = pmac_udma_read; - ide_hwifs[ix].udma_write = pmac_udma_write; + ide_hwifs[ix].udma_init = pmac_udma_init; ide_hwifs[ix].udma_irq_status = pmac_udma_irq_status; - ide_hwifs[ix].XXX_udma = pmac_ide_dmaproc; + ide_hwifs[ix].udma_setup = pmac_udma_setup; #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO if (!noautodma) ide_hwifs[ix].autodma = 1; @@ -1330,7 +1326,7 @@ /* Normal MultiWord DMA modes. */ drive->using_dma = pmac_ide_mdma_enable(drive, idx); } - OUT_BYTE(0, IDE_CONTROL_REG); + ata_irq_enable(drive, 1); /* Apply settings to controller */ pmac_ide_selectproc(drive); } @@ -1405,11 +1401,12 @@ return (dstat & (RUN|DEAD|ACTIVE)) != RUN; } -static int pmac_do_udma(unsigned int reading, struct ata_device *drive, struct request *rq) +static int pmac_udma_init(struct ata_device *drive, struct request *rq) { int ix, ata4; volatile struct dbdma_regs *dma; - byte unit = (drive->select.b.unit & 0x01); + u8 unit = (drive->select.b.unit & 0x01); + int reading; /* Can we stuff a pointer to our intf structure in config_data * or select_data in hwif ? @@ -1417,6 +1414,12 @@ ix = pmac_ide_find(drive); if (ix < 0) return 0; + + if (rq_data_dir(rq) == READ) + reading = 1; + else + reading = 0; + dma = pmac_ide[ix].dma_regs; ata4 = (pmac_ide[ix].kind == controller_kl_ata4 || pmac_ide[ix].kind == controller_kl_ata4_80); @@ -1447,16 +1450,6 @@ return udma_start(drive, rq); } -static int pmac_udma_read(struct ata_device *drive, struct request *rq) -{ - return pmac_do_udma(1, drive, rq); -} - -static int pmac_udma_write(struct ata_device *drive, struct request *rq) -{ - return pmac_do_udma(0, drive, rq); -} - /* * FIXME: This should be attached to a channel as we can see now! */ @@ -1514,7 +1507,7 @@ return 0; } -static int pmac_ide_dmaproc(struct ata_device *drive) +static int pmac_udma_setup(struct ata_device *drive) { /* Change this to better match ide-dma.c */ pmac_ide_check_dma(drive); @@ -1584,9 +1577,9 @@ */ if (used_dma && !ide_spin_wait_hwgroup(drive)) { /* Lock HW group */ - set_bit(IDE_BUSY, &drive->channel->active); + set_bit(IDE_BUSY, drive->channel->active); pmac_ide_check_dma(drive); - clear_bit(IDE_BUSY, &drive->channel->active); + clear_bit(IDE_BUSY, drive->channel->active); spin_unlock_irq(drive->channel->lock); } #endif @@ -1633,7 +1626,7 @@ return; else { /* Lock HW group */ - set_bit(IDE_BUSY, &drive->channel->active); + set_bit(IDE_BUSY, drive->channel->active); /* Stop the device */ idepmac_sleep_device(drive, idx, base); spin_unlock_irq(drive->channel->lock); @@ -1663,7 +1656,7 @@ /* We resume processing on the lock group */ spin_lock_irq(drive->channel->lock); - clear_bit(IDE_BUSY, &drive->channel->active); + clear_bit(IDE_BUSY, drive->channel->active); if (!list_empty(&drive->queue.queue_head)) do_ide_request(&drive->queue); spin_unlock_irq(drive->channel->lock); diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c --- a/drivers/ide/ide-tape.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/ide-tape.c Sun Jun 2 18:44:56 2002 @@ -702,16 +702,6 @@ } idetape_chrdev_direction_t; /* - * Packet command flag bits. - */ -#define PC_ABORT 0 /* Set when an error is considered normal - We won't retry */ -#define PC_WAIT_FOR_DSC 1 /* 1 When polling for DSC on a media access command */ -#define PC_DMA_RECOMMENDED 2 /* 1 when we prefer to use DMA if possible */ -#define PC_DMA_IN_PROGRESS 3 /* 1 while DMA in progress */ -#define PC_DMA_ERROR 4 /* 1 when encountered problem during DMA */ -#define PC_WRITING 5 /* Data direction */ - -/* * Capabilities and Mechanical Status Page */ typedef struct { @@ -1874,9 +1864,12 @@ idetape_increase_max_pipeline_stages (drive); } } - ide_end_drive_cmd(drive, rq, 0, 0); + blkdev_dequeue_request(rq); + drive->rq = NULL; + end_that_request_last(rq); + if (remove_stage) - idetape_remove_stage_head (drive); + idetape_remove_stage_head(drive); if (tape->active_data_request == NULL) clear_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); spin_unlock_irqrestore(&tape->spinlock, flags); @@ -1931,7 +1924,7 @@ */ static void idetape_queue_pc_head(struct ata_device *drive, struct atapi_packet_command *pc, struct request *rq) { - ide_init_drive_cmd (rq); + memset(rq, 0, sizeof(*rq)); rq->buffer = (char *) pc; rq->flags = IDETAPE_PC_RQ1; ide_do_drive_cmd(drive, rq, ide_preempt); @@ -2001,7 +1994,8 @@ printk (KERN_INFO "ide-tape: Reached idetape_pc_intr interrupt handler\n"); #endif - status.all = GET_STAT(); /* Clear the interrupt */ + ata_status(drive, 0, 0); + status.all = drive->status; /* Clear the interrupt */ #ifdef CONFIG_BLK_DEV_IDEDMA if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { @@ -2264,16 +2258,11 @@ printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n"); udma_enable(drive, 0, 1); } - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) { - if (test_bit (PC_WRITING, &pc->flags)) - dma_ok = !udma_write(drive, rq); - else - dma_ok = !udma_read(drive, rq); - } + if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) + dma_ok = !udma_init(drive, rq); #endif - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl, IDE_CONTROL_REG); + ata_irq_enable(drive, 1); OUT_BYTE (dma_ok ? 1 : 0, IDE_FEATURE_REG); /* Use PIO/DMA */ OUT_BYTE (bcount.b.high, IDE_BCOUNTH_REG); OUT_BYTE (bcount.b.low, IDE_BCOUNTL_REG); @@ -2425,7 +2414,8 @@ if (tape->onstream) printk(KERN_INFO "ide-tape: bug: onstream, media_access_finished\n"); - status.all = GET_STAT(); + ata_status(drive, 0, 0); + status.all = drive->status; if (status.b.dsc) { if (status.b.check) { /* Error detected */ printk (KERN_ERR "ide-tape: %s: I/O error, ",tape->name); @@ -2613,10 +2603,11 @@ tape->postponed_rq = NULL; /* - * If the tape is still busy, postpone our request and service - * the other device meanwhile. + * If the tape is still busy, postpone our request and service + * the other device meanwhile. */ - status.all = GET_STAT(); + ata_status(drive, 0, 0); + status.all = drive->status; /* * The OnStream tape drive doesn't support DSC. Assume @@ -3161,7 +3152,7 @@ { struct request rq; - ide_init_drive_cmd (&rq); + memset(&rq, 0, sizeof(rq)); /* FIXME: --mdcki */ rq.buffer = (char *) pc; rq.flags = IDETAPE_PC_RQ1; @@ -3422,17 +3413,17 @@ #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) printk (KERN_INFO "ide-tape: idetape_queue_rw_tail: cmd=%d\n",cmd); -#endif /* IDETAPE_DEBUG_LOG */ +#endif #if IDETAPE_DEBUG_BUGS if (idetape_pipeline_active (tape)) { printk (KERN_ERR "ide-tape: bug: the pipeline is active in idetape_queue_rw_tail\n"); return (0); } -#endif /* IDETAPE_DEBUG_BUGS */ +#endif - ide_init_drive_cmd (&rq); - rq.bio = bio; + memset(&rq, 0, sizeof(rq)); rq.flags = cmd; + rq.bio = bio; rq.sector = tape->first_frame_position; rq.nr_sectors = rq.current_nr_sectors = blocks; if (tape->onstream) @@ -3480,7 +3471,7 @@ printk(KERN_INFO "ide-tape: %s: read back logical block %d, data %x %x %x %x\n", tape->name, logical_blk_num, *p++, *p++, *p++, *p++); #endif rq = &stage->rq; - ide_init_drive_cmd (rq); + memset(rq, 0, sizeof(*rq)); rq->flags = IDETAPE_WRITE_RQ; rq->sector = tape->first_frame_position; rq->nr_sectors = rq->current_nr_sectors = tape->capabilities.ctl; @@ -3756,7 +3747,7 @@ } } rq = &new_stage->rq; - ide_init_drive_cmd (rq); + memset(rq, 0, sizeof(*rq)); rq->flags = IDETAPE_WRITE_RQ; rq->sector = tape->first_frame_position; /* Doesn't actually matter - We always assume sequential access */ rq->nr_sectors = rq->current_nr_sectors = blocks; @@ -3946,7 +3937,8 @@ } if (tape->restart_speed_control_req) idetape_restart_speed_control(drive); - ide_init_drive_cmd (&rq); + + memset(&rq, 0, sizeof(rq)); rq.flags = IDETAPE_READ_RQ; rq.sector = tape->first_frame_position; rq.nr_sectors = rq.current_nr_sectors = blocks; diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c --- a/drivers/ide/ide-taskfile.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ide/ide-taskfile.c Sun Jun 2 18:44:57 2002 @@ -1,4 +1,5 @@ -/* +/**** vi:set ts=8 sts=8 sw=8:************************************************ + * * Copyright (C) 2002 Marcin Dalecki * Copyright (C) 2000 Michael Cornwell * Copyright (C) 2000 Andre Hedrick @@ -165,14 +166,15 @@ */ int drive_is_ready(struct ata_device *drive) { - byte stat = 0; if (drive->waiting_for_dma) return udma_irq_status(drive); -#if 0 - /* need to guarantee 400ns since last command was issued */ - udelay(1); -#endif + /* + * Need to guarantee 400ns since last command was issued? + */ + + /* FIXME: promote this to the general status read method perhaps. + */ #ifdef CONFIG_IDEPCI_SHARE_IRQ /* * We do a passive status test under shared PCI interrupts on @@ -180,16 +182,16 @@ * an interrupt with another pci card/device. We make no assumptions * about possible isa-pnp and pci-pnp issues yet. */ - if (IDE_CONTROL_REG) - stat = GET_ALTSTAT(); + if (drive->channel->io_ports[IDE_CONTROL_OFFSET]) + drive->status = GET_ALTSTAT(); else #endif - stat = GET_STAT(); /* Note: this may clear a pending IRQ!! */ + ata_status(drive, 0, 0); /* Note: this may clear a pending IRQ! */ - if (stat & BUSY_STAT) + if (drive->status & BUSY_STAT) return 0; /* drive busy: definitely not interrupting */ - return 1; /* drive ready: *might* be interrupting */ + return 1; /* drive ready: *might* be interrupting */ } /* @@ -228,34 +230,36 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request *rq) { - u8 stat = GET_STAT(); + int ok; int mcount = drive->mult_count; ide_startstop_t startstop; + /* + * FIXME: the drive->status checks here seem to be messy. + * * (ks/hs): Handle last IRQ on multi-sector transfer, * occurs after all data was sent in this chunk */ - if (!rq->nr_sectors) { - if (stat & (ERR_STAT|DRQ_STAT)) { - startstop = ide_error(drive, rq, "task_mulout_intr", stat); + + ok = ata_status(drive, DATA_READY, BAD_R_STAT); + + if (!ok || !rq->nr_sectors) { + if (drive->status & (ERR_STAT | DRQ_STAT)) { + startstop = ata_error(drive, rq, __FUNCTION__); return startstop; } + } + if (!rq->nr_sectors) { __ide_end_request(drive, rq, 1, rq->hard_nr_sectors); rq->bio = NULL; return ide_stopped; } - if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { - if (stat & (ERR_STAT | DRQ_STAT)) { - startstop = ide_error(drive, rq, "task_mulout_intr", stat); - - return startstop; - } - + if (!ok) { /* no data yet, so wait for another interrupt */ if (!drive->channel->handler) ide_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL); @@ -307,59 +311,34 @@ } ide_startstop_t ata_taskfile(struct ata_device *drive, - struct ata_taskfile *args, struct request *rq) + struct ata_taskfile *ar, struct request *rq) { struct hd_driveid *id = drive->id; - u8 HIHI = (drive->addressing) ? 0xE0 : 0xEF; - -#if 0 - printk("ata_taskfile ... %p\n", args->handler); - printk(" sector feature %02x\n", args->taskfile.feature); - printk(" sector count %02x\n", args->taskfile.sector_count); - printk(" drive/head %02x\n", args->taskfile.device_head); - printk(" command %02x\n", args->taskfile.command); + /* (ks/hs): Moved to start, do not use for multiple out commands */ + if (ar->handler != task_mulout_intr) { + ata_irq_enable(drive, 1); + ata_mask(drive); + } - if (rq) - printk(" rq->nr_sectors %2li\n", rq->nr_sectors); - else - printk(" rq-> = null\n"); -#endif + if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400) && + (drive->addressing == 1)) + ata_out_regfile(drive, &ar->hobfile); - /* (ks/hs): Moved to start, do not use for multiple out commands */ - if (args->handler != task_mulout_intr) { - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(drive->channel, drive, 0); - } - - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - OUT_BYTE(args->hobfile.feature, IDE_FEATURE_REG); - OUT_BYTE(args->hobfile.sector_count, IDE_NSECTOR_REG); - OUT_BYTE(args->hobfile.sector_number, IDE_SECTOR_REG); - OUT_BYTE(args->hobfile.low_cylinder, IDE_LCYL_REG); - OUT_BYTE(args->hobfile.high_cylinder, IDE_HCYL_REG); - } - - OUT_BYTE(args->taskfile.feature, IDE_FEATURE_REG); - OUT_BYTE(args->taskfile.sector_count, IDE_NSECTOR_REG); - /* refers to number of sectors to transfer */ - OUT_BYTE(args->taskfile.sector_number, IDE_SECTOR_REG); - /* refers to sector offset or start sector */ - OUT_BYTE(args->taskfile.low_cylinder, IDE_LCYL_REG); - OUT_BYTE(args->taskfile.high_cylinder, IDE_HCYL_REG); + ata_out_regfile(drive, &ar->taskfile); - OUT_BYTE((args->taskfile.device_head & HIHI) | drive->select.all, IDE_SELECT_REG); - if (args->handler != NULL) { + { + u8 HIHI = (drive->addressing) ? 0xE0 : 0xEF; + OUT_BYTE((ar->taskfile.device_head & HIHI) | drive->select.all, IDE_SELECT_REG); + } + if (ar->handler != NULL) { /* This is apparently supposed to reset the wait timeout for * the interrupt to accur. */ - ide_set_handler(drive, args->handler, WAIT_CMD, NULL); - OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG); + ide_set_handler(drive, ar->handler, WAIT_CMD, NULL); + OUT_BYTE(ar->cmd, IDE_COMMAND_REG); /* * Warning check for race between handler and prehandler for @@ -367,34 +346,32 @@ * inside the boundaries of the seek, we should be okay. */ - if (args->prehandler != NULL) - return args->prehandler(drive, rq); + if (ar->prehandler != NULL) + return ar->prehandler(drive, rq); } else { /* - * FIXME: this is a gross hack, need to unify tcq dma proc and - * regular dma proc -- basically split stuff that needs to act - * on a request from things like ide_dma_check etc. + * FIXME: This is a gross hack, need to unify tcq dma proc and + * regular dma proc. It should now be easier. */ if (!drive->using_dma) return ide_started; /* for dma commands we don't set the handler */ - if (args->taskfile.command == WIN_WRITEDMA - || args->taskfile.command == WIN_WRITEDMA_EXT) - return !udma_write(drive, rq); - else if (args->taskfile.command == WIN_READDMA - || args->taskfile.command == WIN_READDMA_EXT) - return !udma_read(drive, rq); + if (ar->cmd == WIN_WRITEDMA + || ar->cmd == WIN_WRITEDMA_EXT + || ar->cmd == WIN_READDMA + || ar->cmd == WIN_READDMA_EXT) + return !udma_init(drive, rq); #ifdef CONFIG_BLK_DEV_IDE_TCQ - else if (args->taskfile.command == WIN_WRITEDMA_QUEUED - || args->taskfile.command == WIN_WRITEDMA_QUEUED_EXT - || args->taskfile.command == WIN_READDMA_QUEUED - || args->taskfile.command == WIN_READDMA_QUEUED_EXT) + else if (ar->cmd == WIN_WRITEDMA_QUEUED + || ar->cmd == WIN_WRITEDMA_QUEUED_EXT + || ar->cmd == WIN_READDMA_QUEUED + || ar->cmd == WIN_READDMA_QUEUED_EXT) return udma_tcq_taskfile(drive, rq); #endif else { - printk("ata_taskfile: unknown command %x\n", args->taskfile.command); + printk(KERN_ERR "%s: unknown command %x\n", __FUNCTION__, ar->cmd); return ide_stopped; } } @@ -407,10 +384,9 @@ */ ide_startstop_t recal_intr(struct ata_device *drive, struct request *rq) { - u8 stat; + if (!ata_status(drive, READY_STAT, BAD_STAT)) + return ata_error(drive, rq, __FUNCTION__); - if (!OK_STAT(stat = GET_STAT(),READY_STAT,BAD_STAT)) - return ide_error(drive, rq, "recal_intr", stat); return ide_stopped; } @@ -419,19 +395,18 @@ */ ide_startstop_t task_no_data_intr(struct ata_device *drive, struct request *rq) { - u8 stat; - struct ata_taskfile *args = rq->special; + struct ata_taskfile *ar = rq->special; ide__sti(); /* local CPU only */ - if (!OK_STAT(stat = GET_STAT(), READY_STAT, BAD_STAT)) { + if (!ata_status(drive, READY_STAT, BAD_STAT)) { /* Keep quiet for NOP because it is expected to fail. */ - if (args && args->taskfile.command != WIN_NOP) - return ide_error(drive, rq, "task_no_data_intr", stat); + if (ar && ar->cmd != WIN_NOP) + return ata_error(drive, rq, __FUNCTION__); } - if (args) - ide_end_drive_cmd(drive, rq, stat, GET_ERR()); + if (ar) + ide_end_drive_cmd(drive, rq); return ide_stopped; } @@ -441,42 +416,41 @@ */ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq) { - u8 stat = GET_STAT(); - char *pBuf = NULL; + char *buf = NULL; unsigned long flags; - if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { - if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, rq, "task_in_intr", stat); - } - if (!(stat & BUSY_STAT)) { + if (!ata_status(drive, DATA_READY, BAD_R_STAT)) { + if (drive->status & (ERR_STAT|DRQ_STAT)) + return ata_error(drive, rq, __FUNCTION__); + + if (!(drive->status & BUSY_STAT)) { DTF("task_in_intr to Soon wait for next interrupt\n"); ide_set_handler(drive, task_in_intr, WAIT_CMD, NULL); + return ide_started; } } - DTF("stat: %02x\n", stat); - pBuf = ide_map_rq(rq, &flags); - DTF("Read: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors); - - ata_read(drive, pBuf, SECTOR_WORDS); - ide_unmap_rq(rq, pBuf, &flags); - - /* - * first segment of the request is complete. note that this does not - * necessarily mean that the entire request is done!! this is only - * true if ide_end_request() returns 0. + DTF("stat: %02x\n", drive->status); + buf = ide_map_rq(rq, &flags); + DTF("Read: %p, rq->current_nr_sectors: %d\n", buf, (int) rq->current_nr_sectors); + + ata_read(drive, buf, SECTOR_WORDS); + ide_unmap_rq(rq, buf, &flags); + + /* First segment of the request is complete. note that this does not + * necessarily mean that the entire request is done!! this is only true + * if ide_end_request() returns 0. */ + if (--rq->current_nr_sectors <= 0) { - DTF("Request Ended stat: %02x\n", GET_STAT()); + DTF("Request Ended stat: %02x\n", drive->status); if (!ide_end_request(drive, rq, 1)) return ide_stopped; } - /* - * still data left to transfer - */ + /* still data left to transfer */ ide_set_handler(drive, task_in_intr, WAIT_CMD, NULL); + return ide_started; } @@ -491,8 +465,8 @@ } /* (ks/hs): Fixed Multi Write */ - if ((args->taskfile.command != WIN_MULTWRITE) && - (args->taskfile.command != WIN_MULTWRITE_EXT)) { + if ((args->cmd != WIN_MULTWRITE) && + (args->cmd != WIN_MULTWRITE_EXT)) { unsigned long flags; char *buf = ide_map_rq(rq, &flags); /* For Write_sectors we need to stuff the first sector */ @@ -511,28 +485,28 @@ */ static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *rq) { - u8 stat = GET_STAT(); - char *pBuf = NULL; + char *buf = NULL; unsigned long flags; - if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) - return ide_error(drive, rq, "task_out_intr", stat); + if (!ata_status(drive, DRIVE_READY, drive->bad_wstat)) + return ata_error(drive, rq, __FUNCTION__); if (!rq->current_nr_sectors) if (!ide_end_request(drive, rq, 1)) return ide_stopped; - if ((rq->nr_sectors == 1) != (stat & DRQ_STAT)) { - pBuf = ide_map_rq(rq, &flags); - DTF("write: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors); + if ((rq->nr_sectors == 1) != (drive->status & DRQ_STAT)) { + buf = ide_map_rq(rq, &flags); + DTF("write: %p, rq->current_nr_sectors: %d\n", buf, (int) rq->current_nr_sectors); - ata_write(drive, pBuf, SECTOR_WORDS); - ide_unmap_rq(rq, pBuf, &flags); + ata_write(drive, buf, SECTOR_WORDS); + ide_unmap_rq(rq, buf, &flags); rq->errors = 0; rq->current_nr_sectors--; } ide_set_handler(drive, task_out_intr, WAIT_CMD, NULL); + return ide_started; } @@ -541,15 +515,14 @@ */ static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request *rq) { - u8 stat; - char *pBuf = NULL; + char *buf = NULL; unsigned int msect, nsect; unsigned long flags; - if (!OK_STAT(stat = GET_STAT(),DATA_READY,BAD_R_STAT)) { - if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, rq, "task_mulin_intr", stat); - } + if (!ata_status(drive, DATA_READY, BAD_R_STAT)) { + if (drive->status & (ERR_STAT|DRQ_STAT)) + return ata_error(drive, rq, __FUNCTION__); + /* no data yet, so wait for another interrupt */ ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); return ide_started; @@ -563,12 +536,12 @@ if (nsect > msect) nsect = msect; - pBuf = ide_map_rq(rq, &flags); + buf = ide_map_rq(rq, &flags); DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %d\n", - pBuf, nsect, rq->current_nr_sectors); - ata_read(drive, pBuf, nsect * SECTOR_WORDS); - ide_unmap_rq(rq, pBuf, &flags); + buf, nsect, rq->current_nr_sectors); + ata_read(drive, buf, nsect * SECTOR_WORDS); + ide_unmap_rq(rq, buf, &flags); rq->errors = 0; rq->current_nr_sectors -= nsect; msect -= nsect; @@ -583,31 +556,28 @@ * more data left */ ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); + return ide_started; } /* Called to figure out the type of command being called. */ -void ide_cmd_type_parser(struct ata_taskfile *args) +void ide_cmd_type_parser(struct ata_taskfile *ar) { - struct hd_drive_task_hdr *taskfile = &args->taskfile; + struct hd_drive_task_hdr *taskfile = &ar->taskfile; - args->prehandler = NULL; - args->handler = NULL; + ar->prehandler = NULL; + ar->handler = NULL; - switch(args->taskfile.command) { + switch (ar->cmd) { case WIN_IDENTIFY: case WIN_PIDENTIFY: - args->handler = task_in_intr; - args->command_type = IDE_DRIVE_TASK_IN; - return; - case CFA_TRANSLATE_SECTOR: case WIN_READ: case WIN_READ_EXT: case WIN_READ_BUFFER: - args->handler = task_in_intr; - args->command_type = IDE_DRIVE_TASK_IN; + ar->handler = task_in_intr; + ar->command_type = IDE_DRIVE_TASK_IN; return; case CFA_WRITE_SECT_WO_ERASE: @@ -616,56 +586,56 @@ case WIN_WRITE_VERIFY: case WIN_WRITE_BUFFER: case WIN_DOWNLOAD_MICROCODE: - args->prehandler = pre_task_out_intr; - args->handler = task_out_intr; - args->command_type = IDE_DRIVE_TASK_RAW_WRITE; + ar->prehandler = pre_task_out_intr; + ar->handler = task_out_intr; + ar->command_type = IDE_DRIVE_TASK_RAW_WRITE; return; case WIN_MULTREAD: case WIN_MULTREAD_EXT: - args->handler = task_mulin_intr; - args->command_type = IDE_DRIVE_TASK_IN; + ar->handler = task_mulin_intr; + ar->command_type = IDE_DRIVE_TASK_IN; return; case CFA_WRITE_MULTI_WO_ERASE: case WIN_MULTWRITE: case WIN_MULTWRITE_EXT: - args->prehandler = pre_task_mulout_intr; - args->handler = task_mulout_intr; - args->command_type = IDE_DRIVE_TASK_RAW_WRITE; + ar->prehandler = pre_task_mulout_intr; + ar->handler = task_mulout_intr; + ar->command_type = IDE_DRIVE_TASK_RAW_WRITE; return; case WIN_SECURITY_DISABLE: case WIN_SECURITY_ERASE_UNIT: case WIN_SECURITY_SET_PASS: case WIN_SECURITY_UNLOCK: - args->handler = task_out_intr; - args->command_type = IDE_DRIVE_TASK_OUT; + ar->handler = task_out_intr; + ar->command_type = IDE_DRIVE_TASK_OUT; return; case WIN_SMART: if (taskfile->feature == SMART_WRITE_LOG_SECTOR) - args->prehandler = pre_task_out_intr; + ar->prehandler = pre_task_out_intr; - args->taskfile.low_cylinder = SMART_LCYL_PASS; - args->taskfile.high_cylinder = SMART_HCYL_PASS; + ar->taskfile.low_cylinder = SMART_LCYL_PASS; + ar->taskfile.high_cylinder = SMART_HCYL_PASS; - switch(args->taskfile.feature) { + switch(ar->taskfile.feature) { case SMART_READ_VALUES: case SMART_READ_THRESHOLDS: case SMART_READ_LOG_SECTOR: - args->handler = task_in_intr; - args->command_type = IDE_DRIVE_TASK_IN; + ar->handler = task_in_intr; + ar->command_type = IDE_DRIVE_TASK_IN; return; case SMART_WRITE_LOG_SECTOR: - args->handler = task_out_intr; - args->command_type = IDE_DRIVE_TASK_OUT; + ar->handler = task_out_intr; + ar->command_type = IDE_DRIVE_TASK_OUT; return; default: - args->handler = task_no_data_intr; - args->command_type = IDE_DRIVE_TASK_NO_DATA; + ar->handler = task_no_data_intr; + ar->command_type = IDE_DRIVE_TASK_NO_DATA; return; } @@ -675,22 +645,22 @@ case WIN_READDMA_QUEUED: case WIN_READDMA_EXT: case WIN_READDMA_QUEUED_EXT: - args->command_type = IDE_DRIVE_TASK_IN; + ar->command_type = IDE_DRIVE_TASK_IN; return; case WIN_WRITEDMA: case WIN_WRITEDMA_QUEUED: case WIN_WRITEDMA_EXT: case WIN_WRITEDMA_QUEUED_EXT: - args->command_type = IDE_DRIVE_TASK_RAW_WRITE; + ar->command_type = IDE_DRIVE_TASK_RAW_WRITE; return; #endif case WIN_SETFEATURES: - args->handler = task_no_data_intr; - switch(args->taskfile.feature) { + ar->handler = task_no_data_intr; + switch (ar->taskfile.feature) { case SETFEATURES_XFER: - args->command_type = IDE_DRIVE_TASK_SET_XFER; + ar->command_type = IDE_DRIVE_TASK_SET_XFER; return; case SETFEATURES_DIS_DEFECT: case SETFEATURES_EN_APM: @@ -708,18 +678,18 @@ case SETFEATURES_DIS_RI: case SETFEATURES_DIS_SI: default: - args->command_type = IDE_DRIVE_TASK_NO_DATA; + ar->command_type = IDE_DRIVE_TASK_NO_DATA; return; } case WIN_SPECIFY: - args->handler = task_no_data_intr; - args->command_type = IDE_DRIVE_TASK_NO_DATA; + ar->handler = task_no_data_intr; + ar->command_type = IDE_DRIVE_TASK_NO_DATA; return; case WIN_RESTORE: - args->handler = recal_intr; - args->command_type = IDE_DRIVE_TASK_NO_DATA; + ar->handler = recal_intr; + ar->command_type = IDE_DRIVE_TASK_NO_DATA; return; case WIN_DIAGNOSE: @@ -749,19 +719,10 @@ case WIN_DOORUNLOCK: case DISABLE_SEAGATE: case EXABYTE_ENABLE_NEST: - - args->handler = task_no_data_intr; - args->command_type = IDE_DRIVE_TASK_NO_DATA; - return; - case WIN_SETMULT: - args->handler = task_no_data_intr; - args->command_type = IDE_DRIVE_TASK_NO_DATA; - return; - case WIN_NOP: - args->handler = task_no_data_intr; - args->command_type = IDE_DRIVE_TASK_NO_DATA; + ar->handler = task_no_data_intr; + ar->command_type = IDE_DRIVE_TASK_NO_DATA; return; case WIN_FORMAT: @@ -770,21 +731,12 @@ case WIN_QUEUED_SERVICE: case WIN_PACKETCMD: default: - args->command_type = IDE_DRIVE_TASK_INVALID; + ar->command_type = IDE_DRIVE_TASK_INVALID; return; } } /* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). - */ -void ide_init_drive_cmd(struct request *rq) -{ - memset(rq, 0, sizeof(*rq)); - rq->flags = REQ_DRIVE_CMD; -} - -/* * This function issues a special IDE device request onto the request queue. * * If action is ide_wait, then the rq is queued at the end of the request @@ -852,151 +804,17 @@ memset(&rq, 0, sizeof(rq)); rq.flags = REQ_DRIVE_ACB; - -#if 0 - if (args->command_type != IDE_DRIVE_TASK_NO_DATA) - rq.current_nr_sectors = rq.nr_sectors - = (args->hobfile.sector_count << 8) - | args->taskfile.sector_count; -#endif rq.special = args; return ide_do_drive_cmd(drive, &rq, ide_wait); } -/* - * Implement generic ioctls invoked from userspace to imlpement specific - * functionality. - * - * Unfortunately every single low level programm out there is using this - * interface. - */ - -/* - * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. - * 1 : Safe to update drive->id DMA registers. - * 0 : OOPs not allowed. - */ -static int set_transfer(struct ata_device *drive, struct ata_taskfile *args) -{ - if ((args->taskfile.command == WIN_SETFEATURES) && - (args->taskfile.sector_number >= XFER_SW_DMA_0) && - (args->taskfile.feature == SETFEATURES_XFER) && - (drive->id->dma_ultra || - drive->id->dma_mword || - drive->id->dma_1word)) - return 1; - - return 0; -} - -/* - * Verify that we are doing an approved SETFEATURES_XFER with respect - * to the hardware being able to support request. Since some hardware - * can improperly report capabilties, we check to see if the host adapter - * in combination with the device (usually a disk) properly detect - * and acknowledge each end of the ribbon. - */ -static int ata66_check(struct ata_device *drive, struct ata_taskfile *args) -{ - if ((args->taskfile.command == WIN_SETFEATURES) && - (args->taskfile.sector_number > XFER_UDMA_2) && - (args->taskfile.feature == SETFEATURES_XFER)) { - if (!drive->channel->udma_four) { - printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->channel->name); - return 1; - } -#ifndef CONFIG_IDEDMA_IVB - if ((drive->id->hw_config & 0x6000) == 0) { -#else - if (((drive->id->hw_config & 0x2000) == 0) || - ((drive->id->hw_config & 0x4000) == 0)) { -#endif - printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->name); - return 1; - } - } - return 0; -} - -int ide_cmd_ioctl(struct ata_device *drive, unsigned long arg) -{ - int err = 0; - u8 vals[4]; - u8 *argbuf = vals; - u8 pio = 0; - int argsize = 4; - struct ata_taskfile args; - struct request rq; - - ide_init_drive_cmd(&rq); - - /* Wait for drive ready. - */ - if (!arg) - return ide_do_drive_cmd(drive, &rq, ide_wait); - - /* Second phase. - */ - if (copy_from_user(vals, (void *)arg, 4)) - return -EFAULT; - - args.taskfile.feature = vals[2]; - args.taskfile.sector_count = vals[3]; - args.taskfile.sector_number = vals[1]; - args.taskfile.low_cylinder = 0x00; - args.taskfile.high_cylinder = 0x00; - args.taskfile.device_head = 0x00; - args.taskfile.command = vals[0]; - - if (vals[3]) { - argsize = 4 + (SECTOR_WORDS * 4 * vals[3]); - argbuf = kmalloc(argsize, GFP_KERNEL); - if (argbuf == NULL) - return -ENOMEM; - memcpy(argbuf, vals, 4); - memset(argbuf + 4, 0, argsize - 4); - } - - /* Always make sure the transfer reate has been setup. - * FIXME: what about setting up the drive with ->tuneproc? - */ - if (set_transfer(drive, &args)) { - pio = vals[1]; - if (ata66_check(drive, &args)) - goto abort; - } - - /* Issue ATA command and wait for completion. - */ - rq.buffer = argbuf; - err = ide_do_drive_cmd(drive, &rq, ide_wait); - - if (!err && pio) { - /* active-retuning-calls future */ - /* FIXME: what about the setup for the drive?! */ - if (drive->channel->speedproc) - drive->channel->speedproc(drive, pio); - } - -abort: - if (copy_to_user((void *)arg, argbuf, argsize)) - err = -EFAULT; - - if (argsize > 4) - kfree(argbuf); - - return err; -} - EXPORT_SYMBOL(drive_is_ready); EXPORT_SYMBOL(ata_read); EXPORT_SYMBOL(ata_write); EXPORT_SYMBOL(ata_taskfile); EXPORT_SYMBOL(recal_intr); EXPORT_SYMBOL(task_no_data_intr); -EXPORT_SYMBOL(ide_init_drive_cmd); EXPORT_SYMBOL(ide_do_drive_cmd); EXPORT_SYMBOL(ide_raw_taskfile); EXPORT_SYMBOL(ide_cmd_type_parser); -EXPORT_SYMBOL(ide_cmd_ioctl); diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c --- a/drivers/ide/ide.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ide/ide.c Sun Jun 2 18:44:57 2002 @@ -184,31 +184,6 @@ spin_unlock_irqrestore(ch->lock, flags); } -static u8 auto_reduce_xfer(struct ata_device *drive) -{ - if (!drive->crc_count) - return drive->current_speed; - drive->crc_count = 0; - - switch(drive->current_speed) { - case XFER_UDMA_7: return XFER_UDMA_6; - case XFER_UDMA_6: return XFER_UDMA_5; - case XFER_UDMA_5: return XFER_UDMA_4; - case XFER_UDMA_4: return XFER_UDMA_3; - case XFER_UDMA_3: return XFER_UDMA_2; - case XFER_UDMA_2: return XFER_UDMA_1; - case XFER_UDMA_1: return XFER_UDMA_0; - /* - * OOPS we do not goto non Ultra DMA modes - * without iCRC's available we force - * the system to PIO and make the user - * invoke the ATA-1 ATA-2 DMA modes. - */ - case XFER_UDMA_0: - default: return XFER_PIO_4; - } -} - static void check_crc_errors(struct ata_device *drive) { if (!drive->using_dma) @@ -218,7 +193,34 @@ if (drive->crc_count) { udma_enable(drive, 0, 0); if (drive->channel->speedproc) { - u8 pio = auto_reduce_xfer(drive); + u8 pio = XFER_PIO_4; + drive->crc_count = 0; + + switch (drive->current_speed) { + case XFER_UDMA_7: pio = XFER_UDMA_6; + break; + case XFER_UDMA_6: pio = XFER_UDMA_5; + break; + case XFER_UDMA_5: pio = XFER_UDMA_4; + break; + case XFER_UDMA_4: pio = XFER_UDMA_3; + break; + case XFER_UDMA_3: pio = XFER_UDMA_2; + break; + case XFER_UDMA_2: pio = XFER_UDMA_1; + break; + case XFER_UDMA_1: pio = XFER_UDMA_0; + break; + /* + * OOPS we do not goto non Ultra DMA modes + * without iCRC's available we force + * the system to PIO and make the user + * invoke the ATA-1 ATA-2 DMA modes. + */ + case XFER_UDMA_0: + default: + pio = XFER_PIO_4; + } drive->channel->speedproc(drive, pio); } if (drive->current_speed >= XFER_SW_DMA_0) @@ -258,21 +260,21 @@ static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct request *__rq) { struct ata_channel *ch = drive->channel; - u8 stat; - SELECT_DRIVE(ch,drive); - udelay (10); + ata_select(drive, 10); - if (OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) { + if (ata_status(drive, 0, BUSY_STAT)) printk("%s: ATAPI reset complete\n", drive->name); - } else { + else { if (time_before(jiffies, ch->poll_timeout)) { ide_set_handler (drive, atapi_reset_pollfunc, HZ/20, NULL); + return ide_started; /* continue polling */ } ch->poll_timeout = 0; /* end of polling */ - printk("%s: ATAPI reset timed out, status=0x%02x\n", drive->name, stat); - return do_reset1 (drive, 1); /* do it the old fashioned way */ + printk("%s: ATAPI reset timed out, status=0x%02x\n", drive->name, drive->status); + + return do_reset1(drive, 1); /* do it the old fashioned way */ } ch->poll_timeout = 0; /* done polling */ @@ -287,16 +289,18 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *__rq) { struct ata_channel *ch = drive->channel; - u8 stat; - if (!OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) { + if (!ata_status(drive, 0, BUSY_STAT)) { if (time_before(jiffies, ch->poll_timeout)) { ide_set_handler(drive, reset_pollfunc, HZ/20, NULL); + return ide_started; /* continue polling */ } - printk("%s: reset timed out, status=0x%02x\n", ch->name, stat); + printk("%s: reset timed out, status=0x%02x\n", ch->name, drive->status); drive->failures++; } else { + u8 stat; + printk("%s: reset: ", ch->name); if ((stat = GET_ERR()) == 1) { printk("success\n"); @@ -360,8 +364,7 @@ /* For an ATAPI device, first try an ATAPI SRST. */ if (drive->type != ATA_DISK && !do_not_try_atapi) { check_crc_errors(drive); - SELECT_DRIVE(ch, drive); - udelay (20); + ata_select(drive, 20); OUT_BYTE(WIN_SRST, IDE_COMMAND_REG); ch->poll_timeout = jiffies + WAIT_WORSTCASE; ide_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL); @@ -377,42 +380,6 @@ for (unit = 0; unit < MAX_DRIVES; ++unit) check_crc_errors(&ch->drives[unit]); -#if OK_TO_RESET_CONTROLLER - if (!IDE_CONTROL_REG) { - __restore_flags(flags); - - return ide_stopped; - } - /* - * Note that we also set nIEN while resetting the device, - * to mask unwanted interrupts from the interface during the reset. - * However, due to the design of PC hardware, this will cause an - * immediate interrupt due to the edge transition it produces. - * This single interrupt gives us a "fast poll" for drives that - * recover from reset very quickly, saving us the first 50ms wait time. - */ - OUT_BYTE(drive->ctl|6,IDE_CONTROL_REG); /* set SRST and nIEN */ - udelay(10); /* more than enough time */ - if (drive->quirk_list == 2) { - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear SRST and nIEN */ - } else { - OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */ - } - udelay(10); /* more than enough time */ - ch->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler(drive, reset_pollfunc, HZ/20, NULL); - - /* - * Some weird controller like resetting themselves to a strange - * state when the disks are reset this way. At least, the Winbond - * 553 documentation says that - */ - if (ch->resetproc != NULL) - ch->resetproc(drive); - - /* FIXME: we should handle mulit mode setting here as well ! */ -#endif - __restore_flags (flags); /* local CPU only */ return ide_started; @@ -420,8 +387,8 @@ static inline u32 read_24(struct ata_device *drive) { - return (IN_BYTE(IDE_HCYL_REG)<<16) | - (IN_BYTE(IDE_LCYL_REG)<<8) | + return (IN_BYTE(IDE_HCYL_REG) << 16) | + (IN_BYTE(IDE_LCYL_REG) << 8) | IN_BYTE(IDE_SECTOR_REG); } @@ -430,40 +397,29 @@ * * Should be called under lock held. */ -void ide_end_drive_cmd(struct ata_device *drive, struct request *rq, u8 stat, u8 err) +void ide_end_drive_cmd(struct ata_device *drive, struct request *rq) { - if (rq->flags & REQ_DRIVE_CMD) { - u8 *args = rq->buffer; - rq->errors = !OK_STAT(stat, READY_STAT, BAD_STAT); - if (args) { - args[0] = stat; - args[1] = err; - args[2] = IN_BYTE(IDE_NSECTOR_REG); - } - } else if (rq->flags & REQ_DRIVE_ACB) { - struct ata_taskfile *args = rq->special; - - rq->errors = !OK_STAT(stat, READY_STAT, BAD_STAT); - if (args) { - args->taskfile.feature = err; - args->taskfile.sector_count = IN_BYTE(IDE_NSECTOR_REG); - args->taskfile.sector_number = IN_BYTE(IDE_SECTOR_REG); - args->taskfile.low_cylinder = IN_BYTE(IDE_LCYL_REG); - args->taskfile.high_cylinder = IN_BYTE(IDE_HCYL_REG); - args->taskfile.device_head = IN_BYTE(IDE_SELECT_REG); - args->taskfile.command = stat; + if (rq->flags & REQ_DRIVE_ACB) { + struct ata_taskfile *ar = rq->special; + + rq->errors = !ata_status(drive, READY_STAT, BAD_STAT); + if (ar) { + ar->taskfile.feature = IN_BYTE(IDE_ERROR_REG); + ar->taskfile.sector_count = IN_BYTE(IDE_NSECTOR_REG); + ar->taskfile.sector_number = IN_BYTE(IDE_SECTOR_REG); + ar->taskfile.low_cylinder = IN_BYTE(IDE_LCYL_REG); + ar->taskfile.high_cylinder = IN_BYTE(IDE_HCYL_REG); + ar->taskfile.device_head = IN_BYTE(IDE_SELECT_REG); if ((drive->id->command_set_2 & 0x0400) && (drive->id->cfs_enable_2 & 0x0400) && (drive->addressing == 1)) { /* The following command goes to the hob file! */ - - OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG); - args->hobfile.feature = IN_BYTE(IDE_FEATURE_REG); - args->hobfile.sector_count = IN_BYTE(IDE_NSECTOR_REG); - - args->hobfile.sector_number = IN_BYTE(IDE_SECTOR_REG); - args->hobfile.low_cylinder = IN_BYTE(IDE_LCYL_REG); - args->hobfile.high_cylinder = IN_BYTE(IDE_HCYL_REG); + OUT_BYTE(0x80, drive->channel->io_ports[IDE_CONTROL_OFFSET]); + ar->hobfile.feature = IN_BYTE(IDE_FEATURE_REG); + ar->hobfile.sector_count = IN_BYTE(IDE_NSECTOR_REG); + ar->hobfile.sector_number = IN_BYTE(IDE_SECTOR_REG); + ar->hobfile.low_cylinder = IN_BYTE(IDE_LCYL_REG); + ar->hobfile.high_cylinder = IN_BYTE(IDE_HCYL_REG); } } } @@ -546,13 +502,13 @@ __u64 sectors = 0; u32 low = 0, high = 0; low = read_24(drive); - OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG); + OUT_BYTE(0x80, drive->channel->io_ports[IDE_CONTROL_OFFSET]); high = read_24(drive); sectors = ((__u64)high << 24) | low; printk(", LBAsect=%lld, high=%d, low=%d", (long long) sectors, high, low); } else { - byte cur = IN_BYTE(IDE_SELECT_REG); + u8 cur = IN_BYTE(IDE_SELECT_REG); if (cur & 0x40) { /* using LBA? */ printk(", LBAsect=%ld", (unsigned long) ((cur&0xf)<<24) @@ -620,7 +576,7 @@ memset(&args, 0, sizeof(args)); args.taskfile.sector_count = drive->sect; - args.taskfile.command = WIN_RESTORE; + args.cmd = WIN_RESTORE; args.handler = recal_intr; ata_taskfile(drive, &args, NULL); } @@ -631,31 +587,34 @@ /* * Take action based on the error returned by the drive. */ -ide_startstop_t ide_error(struct ata_device *drive, struct request *rq, const char *msg, byte stat) +ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const char *msg) { - byte err; + u8 err; + u8 stat = drive->status; err = ide_dump_status(drive, rq, msg, stat); if (!drive || !rq) return ide_stopped; + /* retry only "normal" I/O: */ if (!(rq->flags & REQ_CMD)) { rq->errors = 1; - ide_end_drive_cmd(drive, rq, stat, err); + ide_end_drive_cmd(drive, rq); + return ide_stopped; } - - if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else { + /* other bits are useless when BUSY */ + if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) + rq->errors |= ERROR_RESET; /* FIXME: What's that?! */ + else { if (drive->type == ATA_DISK && (stat & ERR_STAT)) { /* err has different meaning on cdrom and tape */ if (err == ABRT_ERR) { if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) return ide_stopped; /* some newer drives don't support WIN_SPECIFY */ - } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) { + } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) drive->crc_count++; /* UDMA crc error -- just retry the operation */ - } else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */ + else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */ rq->errors = ERROR_MAX; else if (err & TRK0_ERR) /* help it find track zero */ rq->errors |= ERROR_RECAL; @@ -664,8 +623,9 @@ if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ) try_to_flush_leftover_data(drive); } - if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) - OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */ + + if (!ata_status(drive, 0, BUSY_STAT | DRQ_STAT)) + OUT_BYTE(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG); /* force an abort */ if (rq->errors >= ERROR_MAX) { if (ata_ops(drive) && ata_ops(drive)->end_request) @@ -679,51 +639,14 @@ if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) return do_recalibrate(drive); } - return ide_stopped; -} - -/* - * Invoked on completion of a special DRIVE_CMD. - */ -static ide_startstop_t drive_cmd_intr(struct ata_device *drive, struct request *rq) -{ - u8 *args = rq->buffer; - u8 stat = GET_STAT(); - int retries = 10; - - ide__sti(); /* local CPU only */ - if ((stat & DRQ_STAT) && args && args[3]) { - ata_read(drive, &args[4], args[3] * SECTOR_WORDS); - - while (((stat = GET_STAT()) & BUSY_STAT) && retries--) - udelay(100); - } - - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) - return ide_error(drive, rq, "drive_cmd", stat); /* already calls ide_end_drive_cmd */ - ide_end_drive_cmd(drive, rq, stat, GET_ERR()); return ide_stopped; } /* - * Issue a simple drive command. The drive must be selected beforehand. - */ -static void drive_cmd(struct ata_device *drive, u8 cmd, u8 nsect) -{ - ide_set_handler(drive, drive_cmd_intr, WAIT_CMD, NULL); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(drive->channel, drive, 0); - OUT_BYTE(nsect, IDE_NSECTOR_REG); - OUT_BYTE(cmd, IDE_COMMAND_REG); -} - - -/* * Busy-wait for the drive status to be not "busy". Check then the status for * all of the "good" bits and none of the "bad" bits, and if all is okay it - * returns 0. All other cases return 1 after invoking ide_error() -- caller + * returns 0. All other cases return 1 after invoking error handler -- caller * should just return. * * This routine should get fixed to not hog the cpu during extra long waits.. @@ -735,21 +658,22 @@ struct ata_device *drive, struct request *rq, byte good, byte bad, unsigned long timeout) { - u8 stat; int i; /* bail early if we've exceeded max_failures */ if (drive->max_failures && (drive->failures > drive->max_failures)) { *startstop = ide_stopped; + return 1; } - udelay(1); /* spec allows drive 400ns to assert "BUSY" */ - if ((stat = GET_STAT()) & BUSY_STAT) { + /* spec allows drive 400ns to assert "BUSY" */ + udelay(1); + if (!ata_status(drive, 0, BUSY_STAT)) { timeout += jiffies; - while ((stat = GET_STAT()) & BUSY_STAT) { + while (!ata_status(drive, 0, BUSY_STAT)) { if (time_after(jiffies, timeout)) { - *startstop = ide_error(drive, rq, "status timeout", stat); + *startstop = ata_error(drive, rq, "status timeout"); return 1; } } @@ -763,10 +687,10 @@ */ for (i = 0; i < 10; i++) { udelay(1); - if (OK_STAT((stat = GET_STAT()), good, bad)) + if (ata_status(drive, good, bad)) return 0; } - *startstop = ide_error(drive, rq, "status error", stat); + *startstop = ata_error(drive, rq, "status error"); return 1; } @@ -813,7 +737,7 @@ { ide_startstop_t res; - SELECT_DRIVE(ch, drive); + ata_select(drive, 0); if (ide_wait_stat(&res, drive, rq, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { printk(KERN_WARNING "%s: drive not ready for command\n", drive->name); @@ -822,50 +746,15 @@ } } - /* This issues a special drive command, usually initiated by ioctl() - * from the external hdparm program. + /* This issues a special drive command. */ if (rq->flags & REQ_DRIVE_ACB) { - struct ata_taskfile *args = rq->special; - - if (!(args)) - goto args_error; - - ata_taskfile(drive, args, NULL); - - if (((args->command_type == IDE_DRIVE_TASK_RAW_WRITE) || - (args->command_type == IDE_DRIVE_TASK_OUT)) && - args->prehandler && args->handler) - return args->prehandler(drive, rq); - - return ide_started; - } + struct ata_taskfile *ar = rq->special; - if (rq->flags & REQ_DRIVE_CMD) { - u8 *args = rq->buffer; - - if (!(args)) + if (!(ar)) goto args_error; -#ifdef DEBUG - printk("%s: DRIVE_CMD ", drive->name); - printk("cmd=0x%02x ", args[0]); - printk("sc=0x%02x ", args[1]); - printk("fr=0x%02x ", args[2]); - printk("xx=0x%02x\n", args[3]); -#endif - if (args[0] == WIN_SMART) { - OUT_BYTE(0x4f, IDE_LCYL_REG); - OUT_BYTE(0xc2, IDE_HCYL_REG); - OUT_BYTE(args[2],IDE_FEATURE_REG); - OUT_BYTE(args[1],IDE_SECTOR_REG); - drive_cmd(drive, args[0], args[3]); - return ide_started; - } - OUT_BYTE(args[2],IDE_FEATURE_REG); - drive_cmd(drive, args[0], args[1]); - - return ide_started; + return ata_taskfile(drive, ar, NULL); } /* The normal way of execution is to pass and execute the request @@ -905,7 +794,7 @@ #ifdef DEBUG printk("%s: DRIVE_CMD (null)\n", drive->name); #endif - ide_end_drive_cmd(drive, rq, GET_STAT(), GET_ERR()); + ide_end_drive_cmd(drive, rq); return ide_stopped; } @@ -1020,8 +909,7 @@ mod_timer(&channel->timer, sleep); /* we purposely leave hwgroup busy while sleeping */ } else { - /* Ugly, but how can we sleep for the lock otherwise? perhaps - * from tq_disk? */ + /* Ugly, but how can we sleep for the lock otherwise? */ ide_release_lock(&irq_lock);/* for atari only */ clear_bit(IDE_BUSY, channel->active); } @@ -1134,15 +1022,15 @@ ch = drive->channel; - if (channel->sharing_irq && ch != channel && ch->io_ports[IDE_CONTROL_OFFSET]) { - /* set nIEN for previous channel */ - /* FIXME: check this! It appears to act on the current channel! */ - - if (ch->intrproc) - ch->intrproc(drive); - else - OUT_BYTE((drive)->ctl|2, ch->io_ports[IDE_CONTROL_OFFSET]); - } + /* Disable intrerrupts from the drive on the previous channel. + * + * FIXME: This should be only done if we are indeed sharing the same + * interrupt line with it. + * + * FIXME: check this! It appears to act on the current channel! + */ + if (ch != channel && channel->sharing_irq && ch->irq == channel->irq) + ata_irq_enable(drive, 0); /* Remember the last drive we where acting on. */ @@ -1279,7 +1167,7 @@ startstop = ide_stopped; dma_timeout_retry(drive, drive->rq); } else - startstop = ide_error(drive, drive->rq, "irq timeout", GET_STAT()); + startstop = ata_error(drive, drive->rq, "irq timeout"); } enable_irq(ch->irq); @@ -1323,8 +1211,8 @@ int i; for (i = 0; i < MAX_HWIFS; ++i) { - u8 stat; struct ata_channel *ch = &ide_hwifs[i]; + struct ata_device *drive; if (!ch->present) continue; @@ -1332,8 +1220,10 @@ if (ch->irq != irq) continue; - stat = IN_BYTE(ch->io_ports[IDE_STATUS_OFFSET]); - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { + /* FIXME: this is a bit weak */ + drive = &ch->drives[0]; + + if (!ata_status(drive, READY_STAT, BAD_STAT)) { /* Try to not flood the console with msgs */ static unsigned long last_msgtime; static int count; @@ -1342,7 +1232,7 @@ if (time_after(jiffies, last_msgtime + HZ)) { last_msgtime = jiffies; printk("%s: unexpected interrupt, status=0x%02x, count=%d\n", - ch->name, stat, count); + ch->name, drive->status, count); } } } @@ -1569,33 +1459,6 @@ return res; } -void ide_fixstring (byte *s, const int bytecount, const int byteswap) -{ - byte *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */ - - if (byteswap) { - /* convert from big-endian to host byte order */ - for (p = end ; p != s;) { - unsigned short *pp = (unsigned short *) (p -= 2); - *pp = ntohs(*pp); - } - } - - /* strip leading blanks */ - while (s != end && *s == ' ') - ++s; - - /* compress internal blanks and strip trailing blanks */ - while (s != end && *s) { - if (*s++ != ' ' || (s != end && *s && *s != ' ')) - *p++ = *(s-1); - } - - /* wipe out trailing garbage */ - while (p != end) - *p++ = '\0'; -} - struct block_device_operations ide_fops[] = {{ owner: THIS_MODULE, open: ide_open, @@ -1614,8 +1477,8 @@ EXPORT_SYMBOL(ide_set_handler); EXPORT_SYMBOL(ide_dump_status); -EXPORT_SYMBOL(ide_error); -EXPORT_SYMBOL(ide_fixstring); +EXPORT_SYMBOL(ata_error); + EXPORT_SYMBOL(ide_wait_stat); EXPORT_SYMBOL(restart_request); EXPORT_SYMBOL(ide_end_drive_cmd); diff -Nru a/drivers/ide/ioctl.c b/drivers/ide/ioctl.c --- a/drivers/ide/ioctl.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ide/ioctl.c Sun Jun 2 18:44:57 2002 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,99 @@ #include "ioctl.h" /* + * Invoked on completion of a special DRIVE_CMD. + */ +static ide_startstop_t drive_cmd_intr(struct ata_device *drive, struct request *rq) +{ + struct ata_taskfile *ar = rq->special; + + ide__sti(); /* local CPU only */ + if (!ata_status(drive, 0, DRQ_STAT) && ar->taskfile.sector_number) { + int retries = 10; + + ata_read(drive, rq->buffer, ar->taskfile.sector_number * SECTOR_WORDS); + + while (!ata_status(drive, 0, BUSY_STAT) && retries--) + udelay(100); + } + + if (!ata_status(drive, READY_STAT, BAD_STAT)) + return ata_error(drive, rq, __FUNCTION__); /* already calls ide_end_drive_cmd */ + ide_end_drive_cmd(drive, rq); + + return ide_stopped; +} + +/* + * Implement generic ioctls invoked from userspace to imlpement specific + * functionality. + * + * Unfortunately every single low level programm out there is using this + * interface. + */ +static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg) +{ + int err = 0; + u8 vals[4]; + u8 *argbuf = vals; + int argsize = 4; + struct ata_taskfile args; + struct request rq; + + /* Second phase. + */ + if (copy_from_user(vals, (void *)arg, 4)) + return -EFAULT; + + memset(&rq, 0, sizeof(rq)); + rq.flags = REQ_DRIVE_ACB; + + memset(&args, 0, sizeof(args)); + + args.taskfile.feature = vals[2]; + args.taskfile.sector_count = vals[1]; + args.taskfile.sector_number = vals[3]; + if (vals[0] == WIN_SMART) { + args.taskfile.low_cylinder = 0x4f; + args.taskfile.high_cylinder = 0xc2; + } else { + args.taskfile.low_cylinder = 0x00; + args.taskfile.high_cylinder = 0x00; + } + args.taskfile.device_head = 0x00; + args.cmd = vals[0]; + + if (vals[3]) { + argsize = 4 + (SECTOR_WORDS * 4 * vals[3]); + argbuf = kmalloc(argsize, GFP_KERNEL); + if (argbuf == NULL) + return -ENOMEM; + memcpy(argbuf, vals, 4); + memset(argbuf + 4, 0, argsize - 4); + } + + /* Issue ATA command and wait for completion. + */ + args.handler = drive_cmd_intr; + + rq.buffer = argbuf + 4; + rq.special = &args; + err = ide_do_drive_cmd(drive, &rq, ide_wait); + + argbuf[0] = drive->status; + argbuf[1] = args.taskfile.feature; + argbuf[2] = args.taskfile.sector_count; + + if (copy_to_user((void *)arg, argbuf, argsize)) + err = -EFAULT; + + if (argsize > 4) + kfree(argbuf); + + return err; +} + +/* * NOTE: Due to ridiculous coding habbits in the hdparm utility we have to * always return unsigned long in case we are returning simple values. */ @@ -40,7 +134,6 @@ { unsigned int major, minor; struct ata_device *drive; - struct request rq; kdev_t dev; dev = inode->i_rdev; @@ -50,7 +143,6 @@ if ((drive = get_info_ptr(inode->i_rdev)) == NULL) return -ENODEV; - /* Contrary to popular beleve we disallow even the reading of the ioctl * values for users which don't have permission too. We do this becouse * such information could be used by an attacker to deply a simple-user @@ -61,7 +153,6 @@ if (!capable(CAP_SYS_ADMIN)) return -EACCES; - ide_init_drive_cmd(&rq); switch (cmd) { case HDIO_GET_32BIT: { unsigned long val = drive->channel->io_32bit; @@ -96,7 +187,6 @@ /* FIXME: we can see that tuneproc whould do the * locking!. */ - if (ide_spin_wait_hwgroup(drive)) return -EBUSY; @@ -114,7 +204,6 @@ return 0; } - case HDIO_SET_UNMASKINTR: if (arg < 0 || arg > 1) return -EINVAL; @@ -146,7 +235,7 @@ if (!drive->driver) return -EPERM; - if (!drive->id || !(drive->id->capability & 1) || !drive->channel->XXX_udma) + if (!drive->id || !(drive->id->capability & 1) || !drive->channel->udma_setup) return -EPERM; if (ide_spin_wait_hwgroup(drive)) @@ -202,9 +291,6 @@ return 0; } - case BLKRRPART: /* Re-read partition tables */ - return ata_revalidate(inode->i_rdev); - case HDIO_GET_IDENTITY: if (minor(inode->i_rdev) & PARTN_MASK) return -EINVAL; @@ -222,12 +308,6 @@ drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP, (long *) arg); - case HDIO_DRIVE_CMD: - if (!capable(CAP_SYS_RAWIO)) - return -EACCES; - - return ide_cmd_ioctl(drive, arg); - case HDIO_SET_NICE: if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP)))) return -EPERM; @@ -241,6 +321,38 @@ return 0; + case HDIO_GET_BUSSTATE: + if (put_user(drive->channel->bus_state, (long *)arg)) + return -EFAULT; + + return 0; + + case HDIO_SET_BUSSTATE: + if (drive->channel->busproc) + drive->channel->busproc(drive, (int)arg); + + return 0; + + case HDIO_DRIVE_CMD: + if (!arg) { + if (ide_spin_wait_hwgroup(drive)) + return -EBUSY; + else + return 0; + } + + return do_cmd_ioctl(drive, arg); + + /* + * uniform packet command handling + */ + case CDROMEJECT: + case CDROMCLOSETRAY: + return block_ioctl(inode->i_bdev, cmd, arg); + + case BLKRRPART: /* Re-read partition tables */ + return ata_revalidate(inode->i_rdev); + case BLKGETSIZE: case BLKGETSIZE64: case BLKROSET: @@ -253,25 +365,6 @@ case BLKBSZGET: case BLKBSZSET: return blk_ioctl(inode->i_bdev, cmd, arg); - - /* - * uniform packet command handling - */ - case CDROMEJECT: - case CDROMCLOSETRAY: - return block_ioctl(inode->i_bdev, cmd, arg); - - case HDIO_GET_BUSSTATE: - if (put_user(drive->channel->bus_state, (long *)arg)) - return -EFAULT; - - return 0; - - case HDIO_SET_BUSSTATE: - if (drive->channel->busproc) - drive->channel->busproc(drive, (int)arg); - - return 0; /* Now check whatever this particular ioctl has a device type * specific implementation. diff -Nru a/drivers/ide/main.c b/drivers/ide/main.c --- a/drivers/ide/main.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/main.c Sun Jun 2 18:44:56 2002 @@ -205,9 +205,8 @@ struct ata_device *drive = &ch->drives[unit]; drive->type = ATA_DISK; - drive->select.all = (unit<<4)|0xa0; + drive->select.all = (unit << 4) | 0xa0; drive->channel = ch; - drive->ctl = 0x08; drive->ready_stat = READY_STAT; drive->bad_wstat = BAD_W_STAT; sprintf(drive->name, "hd%c", 'a' + (index * MAX_DRIVES) + unit); @@ -521,12 +520,11 @@ ch->ata_write = old.ata_write; ch->atapi_read = old.atapi_read; ch->atapi_write = old.atapi_write; - ch->XXX_udma = old.XXX_udma; + ch->udma_setup = old.udma_setup; ch->udma_enable = old.udma_enable; ch->udma_start = old.udma_start; ch->udma_stop = old.udma_stop; - ch->udma_read = old.udma_read; - ch->udma_write = old.udma_write; + ch->udma_init = old.udma_init; ch->udma_irq_status = old.udma_irq_status; ch->udma_timeout = old.udma_timeout; ch->udma_irq_lost = old.udma_irq_lost; @@ -1093,7 +1091,7 @@ spin_unlock_irqrestore(&ide_lock, flags); /* Default autotune or requested autotune */ if (drive->autotune != 2) { - if (drive->channel->XXX_udma) { + if (drive->channel->udma_setup) { /* * Force DMAing for the beginning of the check. Some @@ -1104,7 +1102,7 @@ */ udma_enable(drive, 0, 0); - drive->channel->XXX_udma(drive); + drive->channel->udma_setup(drive); #ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT udma_tcq_enable(drive, 1); #endif @@ -1293,6 +1291,7 @@ printk(KERN_INFO "ATA/ATAPI device driver v" VERSION "\n"); ide_devfs_handle = devfs_mk_dir(NULL, "ata", NULL); + devfs_mk_symlink(NULL, "ide", DEVFS_FL_DEFAULT, "ata", NULL, NULL); /* * Because most of the ATA adapters represent the timings in unit of @@ -1480,13 +1479,6 @@ #endif #ifdef CONFIG_BLK_DEV_IDEFLOPPY idefloppy_init(); -#endif -#ifdef CONFIG_BLK_DEV_IDESCSI -# ifdef CONFIG_SCSI - idescsi_init(); -# else - #error ATA SCSI emulation selected but no SCSI-subsystem in kernel -# endif #endif initializing = 0; diff -Nru a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c --- a/drivers/ide/ns87415.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ide/ns87415.c Sun Jun 2 18:44:57 2002 @@ -101,11 +101,11 @@ } -static int ns87415_udma_read(struct ata_device *drive, struct request *rq) +static int ns87415_udma_init(struct ata_device *drive, struct request *rq) { ns87415_prepare_drive(drive, 1); /* select DMA xfer */ - if (!ata_do_udma(1, drive, rq)) /* use standard DMA stuff */ + if (!udma_pci_init(drive, rq)) /* use standard DMA stuff */ return 0; ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */ @@ -113,26 +113,14 @@ return 1; } -static int ns87415_udma_write(struct ata_device *drive, struct request *rq) -{ - ns87415_prepare_drive(drive, 1); /* select DMA xfer */ - - if (!ata_do_udma(0, drive, rq)) /* use standard DMA stuff */ - return 0; - - ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */ - - return 1; -} - -static int ns87415_dmaproc(struct ata_device *drive) +static int ns87415_udma_setup(struct ata_device *drive) { if (drive->type != ATA_DISK) { udma_enable(drive, 0, 0); return 0; } - return XXX_ide_dmaproc(drive); + return udma_pci_setup(drive); } #endif @@ -141,10 +129,6 @@ struct pci_dev *dev = hwif->pci_dev; unsigned int ctrl, using_inta; byte progif; -#ifdef __sparc_v9__ - int timeout; - byte stat; -#endif /* Set a good latency timer and cache line size value. */ (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); @@ -195,18 +179,9 @@ #ifdef __sparc_v9__ /* * XXX: Reset the device, if we don't it will not respond - * to SELECT_DRIVE() properly during first probe_hwif(). + * to select properly during first probe. */ - timeout = 10000; - outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]); - udelay(10); - outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - do { - udelay(50); - stat = inb(hwif->io_ports[IDE_STATUS_OFFSET]); - if (stat == 0xff) - break; - } while ((stat & BUSY_STAT) && --timeout); + ata_reset(hwif); #endif } @@ -231,9 +206,8 @@ #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { hwif->udma_stop = ns87415_udma_stop; - hwif->udma_read = ns87415_udma_read; - hwif->udma_write = ns87415_udma_write; - hwif->XXX_udma = ns87415_dmaproc; + hwif->udma_init = ns87415_udma_init; + hwif->udma_setup = ns87415_udma_setup; } #endif diff -Nru a/drivers/ide/pcidma.c b/drivers/ide/pcidma.c --- a/drivers/ide/pcidma.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/pcidma.c Sun Jun 2 18:44:56 2002 @@ -39,10 +39,10 @@ */ ide_startstop_t ide_dma_intr(struct ata_device *drive, struct request *rq) { - u8 stat, dma_stat; - + u8 dma_stat; dma_stat = udma_stop(drive); - if (OK_STAT(stat = GET_STAT(),DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { + + if (ata_status(drive, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) { if (!dma_stat) { __ide_end_request(drive, rq, 1, rq->nr_sectors); return ide_stopped; @@ -50,7 +50,8 @@ printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); } - return ide_error(drive, rq, "dma_intr", stat); + + return ata_error(drive, rq, __FUNCTION__); } /* @@ -119,7 +120,7 @@ static int dma_timer_expiry(struct ata_device *drive, struct request *rq) { /* FIXME: What's that? */ - u8 dma_stat = inb(drive->channel->dma_base+2); + u8 dma_stat = inb(drive->channel->dma_base + 2); #ifdef DEBUG printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat); @@ -130,11 +131,12 @@ #endif if (dma_stat & 2) { /* ERROR */ - u8 stat = GET_STAT(); - return ide_error(drive, rq, "dma_timer_expiry", stat); + ata_status(drive, 0, 0); + return ata_error(drive, rq, __FUNCTION__); } if (dma_stat & 1) /* DMAing */ return WAIT_CMD; + return 0; } @@ -162,7 +164,7 @@ /* * Configure a device for DMA operation. */ -int XXX_ide_dmaproc(struct ata_device *drive) +int udma_pci_setup(struct ata_device *drive) { int config_allows_dma = 1; struct hd_driveid *id = drive->id; @@ -425,16 +427,6 @@ return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ } -int udma_pci_read(struct ata_device *drive, struct request *rq) -{ - return ata_do_udma(1, drive, rq); -} - -int udma_pci_write(struct ata_device *drive, struct request *rq) -{ - return ata_do_udma(0, drive, rq); -} - /* * FIXME: This should be attached to a channel as we can see now! */ @@ -488,18 +480,16 @@ * We could just assign them, and then leave it up to the chipset * specific code to override these after they've called this function. */ - if (!ch->XXX_udma) - ch->XXX_udma = XXX_ide_dmaproc; + if (!ch->udma_setup) + ch->udma_setup = udma_pci_setup; if (!ch->udma_enable) ch->udma_enable = udma_pci_enable; if (!ch->udma_start) ch->udma_start = udma_pci_start; if (!ch->udma_stop) ch->udma_stop = udma_pci_stop; - if (!ch->udma_read) - ch->udma_read = udma_pci_read; - if (!ch->udma_write) - ch->udma_write = udma_pci_write; + if (!ch->udma_init) + ch->udma_init = udma_pci_init; if (!ch->udma_irq_status) ch->udma_irq_status = udma_pci_irq_status; if (!ch->udma_timeout) @@ -526,38 +516,40 @@ * It's exported only for host chips which use it for fallback or (too) late * capability checking. */ - -int ata_do_udma(unsigned int reading, struct ata_device *drive, struct request *rq) +int udma_pci_init(struct ata_device *drive, struct request *rq) { + u8 cmd; + if (ata_start_dma(drive, rq)) return 1; if (drive->type != ATA_DISK) return 0; - reading <<= 3; + if (rq_data_dir(rq) == READ) + cmd = 0x08; + else + cmd = 0x00; ide_set_handler(drive, ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */ if ((rq->flags & REQ_DRIVE_ACB) && (drive->addressing == 1)) { + /* FIXME: this should never happen */ struct ata_taskfile *args = rq->special; - outb(args->taskfile.command, IDE_COMMAND_REG); - } else if (drive->addressing) { - outb(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); - } else { - outb(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - } + outb(args->cmd, IDE_COMMAND_REG); + } else if (drive->addressing) + outb(cmd ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); + else + outb(cmd ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); return udma_start(drive, rq); } -EXPORT_SYMBOL(ata_do_udma); EXPORT_SYMBOL(ide_dma_intr); EXPORT_SYMBOL(udma_pci_enable); EXPORT_SYMBOL(udma_pci_start); EXPORT_SYMBOL(udma_pci_stop); -EXPORT_SYMBOL(udma_pci_read); -EXPORT_SYMBOL(udma_pci_write); +EXPORT_SYMBOL(udma_pci_init); EXPORT_SYMBOL(udma_pci_irq_status); EXPORT_SYMBOL(udma_pci_timeout); EXPORT_SYMBOL(udma_pci_irq_lost); diff -Nru a/drivers/ide/pcihost.h b/drivers/ide/pcihost.h --- a/drivers/ide/pcihost.h Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/pcihost.h Sun Jun 2 18:44:56 2002 @@ -105,13 +105,12 @@ #define ATA_F_DMA 0x001 #define ATA_F_NODMA 0x002 /* no DMA mode supported at all */ #define ATA_F_NOADMA 0x004 /* DMA has to be enabled explicitely */ -#define ATA_F_FDMA 0x008 /* force autodma */ -#define ATA_F_FIXIRQ 0x010 /* fixed irq wiring */ -#define ATA_F_SER 0x020 /* serialize on first and second channel interrupts */ -#define ATA_F_IRQ 0x040 /* trust IRQ information from config */ -#define ATA_F_PHACK 0x080 /* apply PROMISE hacks */ -#define ATA_F_HPTHACK 0x100 /* apply HPT366 hacks */ -#define ATA_F_SIMPLEX 0x200 /* force treatment as simple device */ +#define ATA_F_FIXIRQ 0x008 /* fixed irq wiring */ +#define ATA_F_SER 0x010 /* serialize on first and second channel interrupts */ +#define ATA_F_IRQ 0x020 /* trust IRQ information from config */ +#define ATA_F_PHACK 0x040 /* apply PROMISE hacks */ +#define ATA_F_HPTHACK 0x080 /* apply HPT366 hacks */ +#define ATA_F_SIMPLEX 0x100 /* force treatment as simple device */ struct ata_pci_device { diff -Nru a/drivers/ide/pdc202xx.c b/drivers/ide/pdc202xx.c --- a/drivers/ide/pdc202xx.c Sun Jun 2 18:44:58 2002 +++ b/drivers/ide/pdc202xx.c Sun Jun 2 18:44:58 2002 @@ -563,7 +563,7 @@ return !(hwif->speedproc(drive, mode)); } -static int config_drive_xfer_rate(struct ata_device *drive) +static int pdc202xx_udma_setup(struct ata_device *drive) { struct hd_driveid *id = drive->id; struct ata_channel *hwif = drive->channel; @@ -670,7 +670,7 @@ return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ } -static void pdc202xx_bug (struct ata_device *drive) +static void pdc202xx_bug(struct ata_device *drive) { if (!drive->channel->resetproc) return; @@ -678,17 +678,15 @@ drive->channel->resetproc(drive); } -static int pdc202xx_dmaproc(struct ata_device *drive) -{ - return config_drive_xfer_rate(drive); -} #endif void pdc202xx_new_reset(struct ata_device *drive) { - set_reg_and_wait(0x04,IDE_CONTROL_REG, 1000); - set_reg_and_wait(0x00,IDE_CONTROL_REG, 1000); - printk("PDC202XX: %s channel reset.\n", + ata_reset(drive->channel); + mdelay(1000); + ata_irq_enable(drive, 1); + mdelay(1000); + printk(KERN_INFO "PDC202XX: %s channel reset.\n", drive->channel->unit ? "Secondary" : "Primary"); } @@ -836,7 +834,7 @@ if (hwif->dma_base) { hwif->udma_irq_lost = pdc202xx_bug; hwif->udma_timeout = pdc202xx_bug; - hwif->XXX_udma = pdc202xx_dmaproc; + hwif->udma_setup = pdc202xx_udma_setup; hwif->highmem = 1; if (!noautodma) hwif->autodma = 1; diff -Nru a/drivers/ide/pdc4030.c b/drivers/ide/pdc4030.c --- a/drivers/ide/pdc4030.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/pdc4030.c Sun Jun 2 18:44:56 2002 @@ -243,9 +243,8 @@ if (inb(IDE_NSECTOR_REG) == 0xFF || inb(IDE_SECTOR_REG) == 0xFF) { return 0; } - if (IDE_CONTROL_REG) - outb(0x08, IDE_CONTROL_REG); - if (pdc4030_cmd(drive,PROMISE_GET_CONFIG)) { + ata_irq_enable(drive, 1); + if (pdc4030_cmd(drive, PROMISE_GET_CONFIG)) { return 0; } if (ide_wait_stat(&startstop, drive, NULL, DATA_READY,BAD_W_STAT,WAIT_DRQ)) { @@ -373,15 +372,13 @@ */ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct request *rq) { - u8 stat; int total_remaining; unsigned int sectors_left, sectors_avail, nsect; unsigned long flags; char *to; - if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { - return ide_error(drive, rq, "promise_read_intr", stat); - } + if (!ata_status(drive, DATA_READY, BAD_R_STAT)) + return ata_error(drive, rq, __FUNCTION__); read_again: do { @@ -427,10 +424,10 @@ if (total_remaining > 0) { if (sectors_avail) goto read_next; - stat = GET_STAT(); - if (stat & DRQ_STAT) + ata_status(drive, 0, 0); + if (drive->status & DRQ_STAT) goto read_again; - if (stat & BUSY_STAT) { + if (drive->status & BUSY_STAT) { ide_set_handler(drive, promise_read_intr, WAIT_CMD, NULL); #ifdef DEBUG_READ printk(KERN_DEBUG "%s: promise_read: waiting for" @@ -440,7 +437,7 @@ } printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left " "!DRQ !BUSY\n", drive->name); - return ide_error(drive, rq, "promise read intr", stat); + return ata_error(drive, rq, "promise read intr"); } return ide_stopped; } @@ -457,7 +454,7 @@ { struct ata_channel *ch = drive->channel; - if (GET_STAT() & BUSY_STAT) { + if (!ata_status(drive, 0, BUSY_STAT)) { if (time_before(jiffies, ch->poll_timeout)) { ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); return ide_started; /* continue polling... */ @@ -465,7 +462,7 @@ ch->poll_timeout = 0; printk(KERN_ERR "%s: completion timeout - still busy!\n", drive->name); - return ide_error(drive, rq, "busy timeout", GET_STAT()); + return ata_error(drive, rq, "busy timeout"); } ch->poll_timeout = 0; @@ -542,8 +539,9 @@ return ide_started; /* continue polling... */ } ch->poll_timeout = 0; - printk(KERN_ERR "%s: write timed out!\n",drive->name); - return ide_error(drive, rq, "write timeout", GET_STAT()); + printk(KERN_ERR "%s: write timed out!\n", drive->name); + ata_status(drive, 0, 0); + return ata_error(drive, rq, "write timeout"); } /* @@ -554,7 +552,7 @@ ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", - drive->name, GET_STAT()); + drive->name, drive->status); #endif return ide_started; } @@ -597,7 +595,7 @@ ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " - "status = %02x\n", drive->name, GET_STAT()); + "status = %02x\n", drive->name, drive->status); #endif return ide_started; } @@ -612,28 +610,22 @@ { struct hd_drive_task_hdr *taskfile = &(args->taskfile); unsigned long timeout; - byte stat; /* Check that it's a regular command. If not, bomb out early. */ if (!(rq->flags & REQ_CMD)) { blk_dump_rq_flags(rq, "pdc4030 bad flags"); ide_end_request(drive, rq, 0); + return ide_stopped; } - if (IDE_CONTROL_REG) - outb(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(drive->channel, drive, 0); - - outb(taskfile->feature, IDE_FEATURE_REG); - outb(taskfile->sector_count, IDE_NSECTOR_REG); - /* refers to number of sectors to transfer */ - outb(taskfile->sector_number, IDE_SECTOR_REG); - /* refers to sector offset or start sector */ - outb(taskfile->low_cylinder, IDE_LCYL_REG); - outb(taskfile->high_cylinder, IDE_HCYL_REG); + ata_irq_enable(drive, 1); + ata_mask(drive); + + ata_out_regfile(drive, taskfile); + outb(taskfile->device_head, IDE_SELECT_REG); - outb(taskfile->command, IDE_COMMAND_REG); + outb(args->cmd, IDE_COMMAND_REG); switch (rq_data_dir(rq)) { case READ: @@ -649,8 +641,7 @@ */ timeout = jiffies + HZ/20; /* 50ms wait */ do { - stat=GET_STAT(); - if (stat & DRQ_STAT) { + if (!ata_status(drive, 0, DRQ_STAT)) { udelay(1); return promise_read_intr(drive, rq); } @@ -712,14 +703,9 @@ args.taskfile.low_cylinder = (block>>=8); args.taskfile.high_cylinder = (block>>=8); args.taskfile.device_head = ((block>>8)&0x0f)|drive->select.all; - args.taskfile.command = (rq_data_dir(rq)==READ)?PROMISE_READ:PROMISE_WRITE; - - /* We can't call ide_cmd_type_parser here, since it won't understand - our command, but that doesn't matter, since we don't use the - generic interrupt handlers either. Setup the bits of args that we - will need. */ - args.handler = NULL; - rq->special = &args; + args.cmd = (rq_data_dir(rq) == READ) ? PROMISE_READ : PROMISE_WRITE; + args.handler = NULL; + rq->special = &args; return do_pdc4030_io(drive, &args, rq); } diff -Nru a/drivers/ide/piix.c b/drivers/ide/piix.c --- a/drivers/ide/piix.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ide/piix.c Sun Jun 2 18:44:57 2002 @@ -109,129 +109,6 @@ static char *piix_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" }; /* - * PIIX/ICH /proc entry. - */ - -#if 0 && defined(CONFIG_PROC_FS) - -#include -#include - -byte piix_proc; -int piix_base; -static struct pci_dev *bmide_dev; -extern int (*piix_display_info)(char *, char **, off_t, int); /* ide-proc.c */ - -#define piix_print(format, arg...) p += sprintf(p, format "\n" , ## arg) -#define piix_print_drive(name, format, arg...)\ - p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n"); - -static int piix_get_info(char *buffer, char **addr, off_t offset, int count) -{ - int speed[4], cycle[4], active[4], recover[4], dmaen[4], uen[4], udma[4], umul; - struct pci_dev *dev = bmide_dev; - unsigned int i, u; - unsigned short c, d, e; - unsigned char t; - char *p = buffer; - - piix_print("----------PIIX BusMastering IDE Configuration---------------"); - - piix_print("Driver Version: 1.3"); - piix_print("South Bridge: %s", bmide_dev->name); - - pci_read_config_byte(dev, PCI_REVISION_ID, &t); - piix_print("Revision: IDE %#x", t); - piix_print("Highest DMA rate: %s", piix_config->flags & PIIX_NODMA ? "No DMA" - : piix_dma[piix_config->flags & PIIX_UDMA]); - - piix_print("BM-DMA base: %#x", piix_base); - piix_print("PCI clock: %d.%dMHz", system_bus_speed / 1000, system_bus_speed / 100 % 10); - - piix_print("-----------------------Primary IDE-------Secondary IDE------"); - - pci_read_config_word(dev, PIIX_IDETIM0, &d); - pci_read_config_word(dev, PIIX_IDETIM1, &e); - piix_print("Enabled: %10s%20s", (d & 0x8000) ? "yes" : "no", (e & 0x8000) ? "yes" : "no"); - - c = inb(piix_base + 0x02) | (inb(piix_base + 0x0a) << 8); - piix_print("Simplex only: %10s%20s", (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no"); - - piix_print("Cable Type: %10s%20s", (piix_80w & 1) ? "80w" : "40w", (piix_80w & 2) ? "80w" : "40w"); - - if (!system_bus_speed) - return p - buffer; - - piix_print("-------------------drive0----drive1----drive2----drive3-----"); - - piix_print_drive("Prefetch+Post: ", "%10s", (((i & 2) ? d : e) & (1 << (2 + ((i & 1) << 2)))) ? "yes" : "no"); - - for (i = 0; i < 4; i++) { - - pci_read_config_word(dev, PIIX_IDETIM0 + (i & 2), &d); - if (~piix_config->flags & PIIX_NO_SITRE) - pci_read_config_byte(dev, PIIX_SIDETIM, &t); - - umul = 4; - udma[i] = uen[i] = 0; - active[i] = 12; - recover[i] = 18; - - switch (i & 1) { - case 1: if (~d & 0x10) break; - if ((~piix_config->flags & PIIX_NO_SITRE) && (d & 0x4000)) { - active[i] = 5 - ((t >> (((i & 2) << 1) + 2)) & 3); - recover[i] = 4 - ((t >> (((i & 2) << 1) + 0)) & 3); - break; - } - - case 0: if (~d & 0x01) break; - active[i] = 5 - ((d >> 12) & 3); - recover[i] = 4 - ((d >> 8) & 3); - } - - dmaen[i] = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2)); - cycle[i] = 1000000 / system_bus_speed * (active[i] + recover[i]); - speed[i] = 2 * system_bus_speed / (active[i] + recover[i]); - - if (!(piix_config->flags & PIIX_UDMA)) - continue; - - pci_read_config_byte(dev, PIIX_UDMACTL, &t); - uen[i] = (t & (1 << i)) ? dmaen[i] : 0; - - if (!uen[i]) - continue; - - pci_read_config_word(dev, PIIX_UDMATIM, &e); - pci_read_config_dword(dev, PIIX_IDECFG, &u); - - if (~piix_config->flags & PIIX_VICTORY) { - if ((piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_66 && (u & (1 << i))) umul = 2; - if ((piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_100 && (u & (1 << (i + 12)))) umul = 1; - udma[i] = (4 - ((e >> (i << 2)) & 3)) * umul; - } else udma[i] = (8 - ((e >> (i << 2)) & 7)) * 2; - - speed[i] = 8 * system_bus_speed / udma[i]; - cycle[i] = 250000 * udma[i] / system_bus_speed; - } - - piix_print_drive("Transfer Mode: ", "%10s", dmaen[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO"); - - piix_print_drive("Address Setup: ", "%8dns", (1000000 / system_bus_speed) * 3); - piix_print_drive("Cmd Active: ", "%8dns", (1000000 / system_bus_speed) * 12); - piix_print_drive("Cmd Recovery: ", "%8dns", (1000000 / system_bus_speed) * 18); - piix_print_drive("Data Active: ", "%8dns", (1000000 / system_bus_speed) * active[i]); - piix_print_drive("Data Recovery: ", "%8dns", (1000000 / system_bus_speed) * recover[i]); - piix_print_drive("Cycle Time: ", "%8dns", cycle[i]); - piix_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 1000, speed[i] / 100 % 10); - - return p - buffer; /* hoping it is less than 4K... */ -} - -#endif - -/* * piix_set_speed() writes timing values to the chipset registers */ @@ -376,7 +253,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA -int piix_dmaproc(struct ata_device *drive) +static int piix_udma_setup(struct ata_device *drive) { short w80 = drive->channel->udma_four; @@ -497,19 +374,6 @@ printk(KERN_INFO "PIIX: %s %s controller on pci%s\n", dev->name, piix_dma[piix_config->flags & PIIX_UDMA], dev->slot_name); -/* - * Register /proc/ide/piix entry - */ - -#if 0 && defined(CONFIG_PROC_FS) - if (!piix_proc) { - piix_base = pci_resource_start(dev, 4); - bmide_dev = dev; - piix_display_info = &piix_get_info; - piix_proc = 1; - } -#endif - return 0; } @@ -535,7 +399,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { hwif->highmem = 1; - hwif->XXX_udma = piix_dmaproc; + hwif->udma_setup = piix_udma_setup; # ifdef CONFIG_IDEDMA_AUTO if (!noautodma) hwif->autodma = 1; diff -Nru a/drivers/ide/probe.c b/drivers/ide/probe.c --- a/drivers/ide/probe.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/probe.c Sun Jun 2 18:44:56 2002 @@ -37,10 +37,8 @@ #include #include - extern struct ata_device * get_info_ptr(kdev_t); - /* * This is called from the partition-table code in pt/msdos.c. * @@ -269,6 +267,34 @@ #endif } +void ide_fixstring(char *s, const int bytecount, const int byteswap) +{ + char *p = s; + char *end = &s[bytecount & ~1]; /* bytecount must be even */ + + if (byteswap) { + /* convert from big-endian to host byte order */ + for (p = end ; p != s;) { + unsigned short *pp = (unsigned short *) (p -= 2); + *pp = ntohs(*pp); + } + } + + /* strip leading blanks */ + while (s != end && *s == ' ') + ++s; + + /* compress internal blanks and strip trailing blanks */ + while (s != end && *s) { + if (*s++ != ' ' || (s != end && *s && *s != ' ')) + *p++ = *(s-1); + } + + /* wipe out trailing garbage */ + while (p != end) + *p++ = '\0'; +} + /* * All hosts that use the 80c ribbon must use this! */ @@ -282,7 +308,7 @@ } /* - * Similar to ide_wait_stat(), except it never calls ide_error internally. + * Similar to ide_wait_stat(), except it never calls ata_error internally. * This is a kludge to handle the new ide_config_drive_speed() function, * and should not otherwise be used anywhere. Eventually, the tuneproc's * should be updated to return ide_startstop_t, in which case we can get @@ -294,14 +320,13 @@ */ int ide_config_drive_speed(struct ata_device *drive, byte speed) { - struct ata_channel *hwif = drive->channel; + struct ata_channel *ch = drive->channel; int i; int error = 1; - u8 stat; #if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(__CRIS__) u8 unit = (drive->select.b.unit & 0x01); - outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); + outb(inb(ch->dma_base + 2) & ~(1 << (5 + unit)), ch->dma_base + 2); #endif /* @@ -312,29 +337,28 @@ /* * Select the drive, and issue the SETFEATURES command */ - disable_irq(hwif->irq); /* disable_irq_nosync ?? */ + disable_irq(ch->irq); /* disable_irq_nosync ?? */ udelay(1); - SELECT_DRIVE(drive->channel, drive); - SELECT_MASK(drive->channel, drive, 0); + ata_select(drive, 0); + ata_mask(drive); udelay(1); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); + ata_irq_enable(drive, 0); OUT_BYTE(speed, IDE_NSECTOR_REG); OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); - if ((IDE_CONTROL_REG) && (drive->quirk_list == 2)) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); + if (drive->quirk_list == 2) + ata_irq_enable(drive, 1); udelay(1); /* * Wait for drive to become non-BUSY */ - if ((stat = GET_STAT()) & BUSY_STAT) { + if (!ata_status(drive, 0, BUSY_STAT)) { unsigned long flags, timeout; __save_flags(flags); /* local CPU only */ ide__sti(); /* local CPU only -- for jiffies */ timeout = jiffies + WAIT_CMD; - while ((stat = GET_STAT()) & BUSY_STAT) { + while (!ata_status(drive, 0, BUSY_STAT)) { if (time_after(jiffies, timeout)) break; } @@ -350,18 +374,18 @@ */ for (i = 0; i < 10; i++) { udelay(1); - if (OK_STAT((stat = GET_STAT()), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) { + if (ata_status(drive, DRIVE_READY, BUSY_STAT | DRQ_STAT | ERR_STAT)) { error = 0; break; } } - SELECT_MASK(drive->channel, drive, 0); + ata_mask(drive); - enable_irq(hwif->irq); + enable_irq(ch->irq); if (error) { - ide_dump_status(drive, NULL, "set_drive_speed_status", stat); + ide_dump_status(drive, NULL, "set_drive_speed_status", drive->status); return error; } @@ -371,9 +395,9 @@ #if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(__CRIS__) if (speed > XFER_PIO_4) { - outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2); + outb(inb(ch->dma_base + 2)|(1 << (5 + unit)), ch->dma_base + 2); } else { - outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); + outb(inb(ch->dma_base + 2) & ~(1 << (5 + unit)), ch->dma_base + 2); } #endif @@ -394,6 +418,7 @@ case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; default: break; } + return error; } @@ -449,9 +474,9 @@ || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */ bswap ^= 1; /* Vertos drives may still be weird */ } - ide_fixstring (id->model, sizeof(id->model), bswap); - ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap); - ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap); + ide_fixstring(id->model, sizeof(id->model), bswap); + ide_fixstring(id->fw_rev, sizeof(id->fw_rev), bswap); + ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap); if (strstr(id->model, "E X A B Y T E N E S T")) goto err_misc; @@ -532,7 +557,7 @@ } } drive->type = ATA_DISK; - printk("ATA DISK drive\n"); + printk("DISK drive\n"); /* Initialize our quirk list. */ if (drive->channel->quirkproc) @@ -569,36 +594,40 @@ */ static int identify(struct ata_device *drive, u8 cmd) { - int rc; + struct ata_channel *ch = drive->channel; + int rc = 1; int autoprobe = 0; unsigned long cookie = 0; ide_ioreg_t hd_status; unsigned long timeout; - u8 s; - u8 a; - if (IDE_CONTROL_REG && !drive->channel->irq) { - autoprobe = 1; - cookie = probe_irq_on(); - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* enable device irq */ - } + /* FIXME: perhaps we should be just using allways the status register, + * since it should simplify the code significantly. + */ + if (ch->io_ports[IDE_CONTROL_OFFSET]) { + u8 s; + u8 a; + + if (!drive->channel->irq) { + autoprobe = 1; + cookie = probe_irq_on(); + ata_irq_enable(drive, 1); /* enable device irq */ + } - rc = 1; - if (IDE_CONTROL_REG) { /* take a deep breath */ mdelay(50); - a = IN_BYTE(IDE_ALTSTATUS_REG); - s = IN_BYTE(IDE_STATUS_REG); + a = IN_BYTE(ch->io_ports[IDE_ALTSTATUS_OFFSET]); + s = IN_BYTE(ch->io_ports[IDE_STATUS_OFFSET]); if ((a ^ s) & ~INDEX_STAT) { printk("%s: probing with STATUS(0x%02x) instead of ALTSTATUS(0x%02x)\n", drive->name, s, a); - hd_status = IDE_STATUS_REG; /* ancient Seagate drives, broken interfaces */ + hd_status = ch->io_ports[IDE_STATUS_OFFSET]; /* ancient Seagate drives, broken interfaces */ } else { - hd_status = IDE_ALTSTATUS_REG; /* use non-intrusive polling */ + hd_status = ch->io_ports[IDE_ALTSTATUS_OFFSET]; /* use non-intrusive polling */ } } else { mdelay(50); - hd_status = IDE_STATUS_REG; + hd_status = ch->io_ports[IDE_STATUS_OFFSET]; } /* set features register for atapi identify command to be sure of reply */ @@ -614,7 +643,7 @@ goto out; } else #endif - OUT_BYTE(cmd,IDE_COMMAND_REG); /* ask drive for ID */ + OUT_BYTE(cmd, IDE_COMMAND_REG); /* ask drive for ID */ timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; timeout += jiffies; do { @@ -625,22 +654,23 @@ mdelay(50); /* wait for IRQ and DRQ_STAT */ - if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { + if (ata_status(drive, DRQ_STAT, BAD_R_STAT)) { unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only; some systems need this */ - do_identify(drive, cmd); /* drive returned ID */ - rc = 0; /* drive responded with ID */ - (void) GET_STAT(); /* clear drive IRQ */ - __restore_flags(flags); /* local CPU only */ + __save_flags(flags); /* local CPU only */ + __cli(); /* local CPU only; some systems need this */ + do_identify(drive, cmd); /* drive returned ID */ + rc = 0; /* drive responded with ID */ + ata_status(drive, 0, 0); /* clear drive IRQ */ + __restore_flags(flags); /* local CPU only */ } else rc = 2; /* drive refused ID */ out: if (autoprobe) { int irq; - OUT_BYTE(drive->ctl | 0x02, IDE_CONTROL_REG); /* mask device irq */ - GET_STAT(); /* clear drive IRQ */ + + ata_irq_enable(drive, 0); /* mask device irq */ + ata_status(drive, 0, 0); /* clear drive IRQ */ udelay(5); irq = probe_irq_off(cookie); if (!drive->channel->irq) { @@ -673,54 +703,54 @@ static int do_probe(struct ata_device *drive, u8 cmd) { int rc; - struct ata_channel *hwif = drive->channel; + struct ata_channel *ch = drive->channel; + u8 select; if (drive->present) { /* avoid waiting for inappropriate probes */ if ((drive->type != ATA_DISK) && (cmd == WIN_IDENTIFY)) return 4; } #ifdef DEBUG - printk("probing for %s: present=%d, type=%d, probetype=%s\n", + printk("probing for %s: present=%d, type=%02x, probetype=%s\n", drive->name, drive->present, drive->type, (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI"); #endif mdelay(50); /* needed for some systems (e.g. crw9624 as drive0 with disk as slave) */ - SELECT_DRIVE(hwif,drive); - mdelay(50); - if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) { + ata_select(drive, 50000); + select = IN_BYTE(IDE_SELECT_REG); + if (select != drive->select.all && !drive->present) { if (drive->select.b.unit != 0) { - SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */ - mdelay(50); /* allow BUSY_STAT to assert & clear */ + ata_select(&ch->drives[0], 50000); /* exit with drive0 selected */ } return 3; /* no i/f present: mmm.. this should be a 4 -ml */ } - if (OK_STAT(GET_STAT(),READY_STAT,BUSY_STAT) || drive->present || cmd == WIN_PIDENTIFY) - { + if (ata_status(drive, READY_STAT, BUSY_STAT) || drive->present || cmd == WIN_PIDENTIFY) { if ((rc = identify(drive,cmd))) /* send cmd and wait */ rc = identify(drive,cmd); /* failed: try again */ if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) { unsigned long timeout; - printk("%s: no response (status = 0x%02x), resetting drive\n", drive->name, GET_STAT()); + printk("%s: no response (status = 0x%02x), resetting drive\n", + drive->name, drive->status); mdelay(50); - OUT_BYTE (drive->select.all, IDE_SELECT_REG); + OUT_BYTE(drive->select.all, IDE_SELECT_REG); mdelay(50); OUT_BYTE(WIN_SRST, IDE_COMMAND_REG); timeout = jiffies; - while ((GET_STAT() & BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE)) + while (!ata_status(drive, 0, BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE)) mdelay(50); rc = identify(drive, cmd); } if (rc == 1) - printk("%s: no response (status = 0x%02x)\n", drive->name, GET_STAT()); - (void) GET_STAT(); /* ensure drive irq is clear */ + printk("%s: no response (status = 0x%02x)\n", + drive->name, drive->status); + ata_status(drive, 0, 0); /* ensure drive irq is clear */ } else rc = 3; /* not present or maybe ATAPI */ if (drive->select.b.unit != 0) { - SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */ - mdelay(50); - GET_STAT(); /* ensure drive irq is clear */ + ata_select(&ch->drives[0], 50000); /* exit with drive0 selected */ + ata_status(drive, 0, 0); /* ensure drive irq is clear */ } return rc; @@ -764,8 +794,7 @@ unsigned long timeout; printk("%s: enabling %s -- ", drive->channel->name, drive->id->model); - SELECT_DRIVE(drive->channel, drive); - mdelay(50); + ata_select(drive, 50000); OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG); timeout = jiffies + WAIT_WORSTCASE; do { @@ -774,10 +803,10 @@ return; } mdelay(50); - } while (GET_STAT() & BUSY_STAT); + } while (!ata_status(drive, 0, BUSY_STAT)); mdelay(50); - if (!OK_STAT(GET_STAT(), 0, BAD_STAT)) - printk("failed (status = 0x%02x)\n", GET_STAT()); + if (!ata_status(drive, 0, BAD_STAT)) + printk("failed (status = 0x%02x)\n", drive->status); else printk("success\n"); @@ -858,19 +887,8 @@ device_register(&ch->dev); - if (ch->reset && ch->io_ports[IDE_CONTROL_OFFSET]) { - unsigned long timeout = jiffies + WAIT_WORSTCASE; - u8 stat; - - printk("%s: reset\n", ch->name); - OUT_BYTE(12, ch->io_ports[IDE_CONTROL_OFFSET]); - udelay(10); - OUT_BYTE(8, ch->io_ports[IDE_CONTROL_OFFSET]); - do { - mdelay(50); - stat = IN_BYTE(ch->io_ports[IDE_STATUS_OFFSET]); - } while ((stat & BUSY_STAT) && time_before(jiffies, timeout)); - } + if (ch->reset) + ata_reset(ch); __restore_flags(flags); /* local CPU only */ @@ -972,14 +990,19 @@ * Allocate the irq, if not already obtained for another channel */ if (!match || match->irq != ch->irq) { + struct ata_device tmp; #ifdef CONFIG_IDEPCI_SHARE_IRQ int sa = IDE_CHIPSET_IS_PCI(ch->chipset) ? SA_SHIRQ : SA_INTERRUPT; #else int sa = IDE_CHIPSET_IS_PCI(ch->chipset) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT; #endif - if (ch->io_ports[IDE_CONTROL_OFFSET]) - OUT_BYTE(0x08, ch->io_ports[IDE_CONTROL_OFFSET]); /* clear nIEN */ + /* Enable interrupts triggered by the drive. We use a shallow + * device structure, just to use the generic function very + * early. + */ + tmp.channel = ch; + ata_irq_enable(&tmp, 1); if (request_irq(ch->irq, &ata_irq_request, sa, ch->name, ch)) { if (!match) { @@ -1243,5 +1266,6 @@ } EXPORT_SYMBOL(ata_fix_driveid); +EXPORT_SYMBOL(ide_fixstring); EXPORT_SYMBOL(eighty_ninty_three); EXPORT_SYMBOL(ide_config_drive_speed); diff -Nru a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c --- a/drivers/ide/qd65xx.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ide/qd65xx.c Sun Jun 2 18:44:57 2002 @@ -173,9 +173,7 @@ if (!*drive->id->model) return 0; - strncpy(model,drive->id->model,40); - ide_fixstring(model,40,1); /* byte-swap */ - + strncpy(model,drive->id->model, 40); for (p = qd65xx_timing ; p->offset != -1 ; p++) { if (!strncmp(p->model, model+p->offset, 4)) { printk(KERN_DEBUG "%s: listed !\n", drive->name); diff -Nru a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c --- a/drivers/ide/serverworks.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ide/serverworks.c Sun Jun 2 18:44:57 2002 @@ -95,146 +95,10 @@ #include "ata-timing.h" #include "pcihost.h" -#undef DISPLAY_SVWKS_TIMINGS #undef SVWKS_DEBUG_DRIVE_INFO static u8 svwks_revision; -#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static struct pci_dev *bmide_dev; - -static int svwks_get_info(char *, char **, off_t, int); -extern int (*svwks_display_info)(char *, char **, off_t, int); /* ide-proc.c */ - -static int svwks_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - u32 reg40, reg44; - u16 reg48, reg56; - u8 reg54, c0=0, c1=0; - - pci_read_config_dword(bmide_dev, 0x40, ®40); - pci_read_config_dword(bmide_dev, 0x44, ®44); - pci_read_config_word(bmide_dev, 0x48, ®48); - pci_read_config_byte(bmide_dev, 0x54, ®54); - pci_read_config_word(bmide_dev, 0x56, ®56); - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - switch(bmide_dev->device) { - case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: - p += sprintf(p, "\n " - "ServerWorks CSB5 Chipset (rev %02x)\n", - svwks_revision); - break; - case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: - p += sprintf(p, "\n " - "ServerWorks OSB4 Chipset (rev %02x)\n", - svwks_revision); - break; - default: - p += sprintf(p, "\n " - "ServerWorks %04x Chipset (rev %02x)\n", - bmide_dev->device, svwks_revision); - break; - } - - p += sprintf(p, "------------------------------- General Status ---------------------------------\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", - (reg54 & 0x01) ? "yes" : "no ", - (reg54 & 0x02) ? "yes" : "no ", - (reg54 & 0x04) ? "yes" : "no ", - (reg54 & 0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", - ((reg56&0x0005)==0x0005)?"5": - ((reg56&0x0004)==0x0004)?"4": - ((reg56&0x0003)==0x0003)?"3": - ((reg56&0x0002)==0x0002)?"2": - ((reg56&0x0001)==0x0001)?"1": - ((reg56&0x000F))?"?":"0", - ((reg56&0x0050)==0x0050)?"5": - ((reg56&0x0040)==0x0040)?"4": - ((reg56&0x0030)==0x0030)?"3": - ((reg56&0x0020)==0x0020)?"2": - ((reg56&0x0010)==0x0010)?"1": - ((reg56&0x00F0))?"?":"0", - ((reg56&0x0500)==0x0500)?"5": - ((reg56&0x0400)==0x0400)?"4": - ((reg56&0x0300)==0x0300)?"3": - ((reg56&0x0200)==0x0200)?"2": - ((reg56&0x0100)==0x0100)?"1": - ((reg56&0x0F00))?"?":"0", - ((reg56&0x5000)==0x5000)?"5": - ((reg56&0x4000)==0x4000)?"4": - ((reg56&0x3000)==0x3000)?"3": - ((reg56&0x2000)==0x2000)?"2": - ((reg56&0x1000)==0x1000)?"1": - ((reg56&0xF000))?"?":"0"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - ((reg44&0x00002000)==0x00002000)?"2": - ((reg44&0x00002100)==0x00002100)?"1": - ((reg44&0x00007700)==0x00007700)?"0": - ((reg44&0x0000FF00)==0x0000FF00)?"X":"?", - ((reg44&0x00000020)==0x00000020)?"2": - ((reg44&0x00000021)==0x00000021)?"1": - ((reg44&0x00000077)==0x00000077)?"0": - ((reg44&0x000000FF)==0x000000FF)?"X":"?", - ((reg44&0x20000000)==0x20000000)?"2": - ((reg44&0x21000000)==0x21000000)?"1": - ((reg44&0x77000000)==0x77000000)?"0": - ((reg44&0xFF000000)==0xFF000000)?"X":"?", - ((reg44&0x00200000)==0x00200000)?"2": - ((reg44&0x00210000)==0x00210000)?"1": - ((reg44&0x00770000)==0x00770000)?"0": - ((reg44&0x00FF0000)==0x00FF0000)?"X":"?"); - - p += sprintf(p, "PIO enabled: %s %s %s %s\n", - ((reg40&0x00002000)==0x00002000)?"4": - ((reg40&0x00002200)==0x00002200)?"3": - ((reg40&0x00003400)==0x00003400)?"2": - ((reg40&0x00004700)==0x00004700)?"1": - ((reg40&0x00005D00)==0x00005D00)?"0":"?", - ((reg40&0x00000020)==0x00000020)?"4": - ((reg40&0x00000022)==0x00000022)?"3": - ((reg40&0x00000034)==0x00000034)?"2": - ((reg40&0x00000047)==0x00000047)?"1": - ((reg40&0x0000005D)==0x0000005D)?"0":"?", - ((reg40&0x20000000)==0x20000000)?"4": - ((reg40&0x22000000)==0x22000000)?"3": - ((reg40&0x34000000)==0x34000000)?"2": - ((reg40&0x47000000)==0x47000000)?"1": - ((reg40&0x5D000000)==0x5D000000)?"0":"?", - ((reg40&0x00200000)==0x00200000)?"4": - ((reg40&0x00220000)==0x00220000)?"3": - ((reg40&0x00340000)==0x00340000)?"2": - ((reg40&0x00470000)==0x00470000)?"1": - ((reg40&0x005D0000)==0x005D0000)?"0":"?"); - return p-buffer; /* => must be less than 4k! */ -} - -static byte svwks_proc; - -#endif /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */ - #define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ static struct pci_dev *isa_dev; @@ -426,7 +290,7 @@ return !svwks_tune_chipset(drive, mode); } -static int config_drive_xfer_rate(struct ata_device *drive) +static int svwks_udma_setup(struct ata_device *drive) { struct hd_driveid *id = drive->id; int on = 1; @@ -523,11 +387,6 @@ return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ } - -static int svwks_dmaproc(struct ata_device *drive) -{ - return config_drive_xfer_rate(drive); -} #endif static unsigned int __init svwks_init_chipset(struct pci_dev *dev) @@ -570,13 +429,6 @@ pci_write_config_byte(dev, 0x5A, btr); } -#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) - if (!svwks_proc) { - svwks_proc = 1; - bmide_dev = dev; - svwks_display_info = &svwks_get_info; - } -#endif /* DISPLAY_SVWKS_TIMINGS && CONFIG_PROC_FS */ return 0; } @@ -649,7 +501,7 @@ hwif->autodma = 1; #endif hwif->udma_stop = svwks_udma_stop; - hwif->XXX_udma = svwks_dmaproc; + hwif->udma_setup = svwks_udma_setup; hwif->highmem = 1; } else { hwif->autodma = 0; diff -Nru a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c --- a/drivers/ide/sis5513.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ide/sis5513.c Sun Jun 2 18:44:57 2002 @@ -59,7 +59,6 @@ /* When BROKEN_LEVEL is defined it limits the DMA mode at boot time to its value */ // #define BROKEN_LEVEL XFER_SW_DMA_0 -#undef DISPLAY_SIS_TIMINGS /* Miscellaneaous flags */ #define SIS5513_LATENCY 0x01 @@ -208,207 +207,6 @@ static struct pci_dev *host_dev = NULL; - -/* - * Printing configuration - */ -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int sis_get_info(char *, char **, off_t, int); -extern int (*sis_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -static char* cable_type[] = { - "80 pins", - "40 pins" -}; - -static char* recovery_time[] ={ - "12 PCICLK", "1 PCICLK", - "2 PCICLK", "3 PCICLK", - "4 PCICLK", "5 PCICLCK", - "6 PCICLK", "7 PCICLCK", - "8 PCICLK", "9 PCICLCK", - "10 PCICLK", "11 PCICLK", - "13 PCICLK", "14 PCICLK", - "15 PCICLK", "15 PCICLK" -}; - -static char* active_time[] = { - "8 PCICLK", "1 PCICLCK", - "2 PCICLK", "3 PCICLK", - "4 PCICLK", "5 PCICLK", - "6 PCICLK", "12 PCICLK" -}; - -static char* cycle_time[] = { - "Reserved", "2 CLK", - "3 CLK", "4 CLK", - "5 CLK", "6 CLK", - "7 CLK", "8 CLK", - "9 CLK", "10 CLK", - "11 CLK", "12 CLK", - "Reserved", "Reserved", - "Reserved", "Reserved" -}; - -/* Generic add master or slave info function */ -static char* get_drives_info (char *buffer, byte pos) -{ - byte reg00, reg01, reg10, reg11; /* timing registers */ - char* p = buffer; - -/* Postwrite/Prefetch */ - pci_read_config_byte(bmide_dev, 0x4b, ®00); - p += sprintf(p, "Drive %d: Postwrite %s \t \t Postwrite %s\n", - pos, (reg00 & (0x10 << pos)) ? "Enabled" : "Disabled", - (reg00 & (0x40 << pos)) ? "Enabled" : "Disabled"); - p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", - (reg00 & (0x01 << pos)) ? "Enabled" : "Disabled", - (reg00 & (0x04 << pos)) ? "Enabled" : "Disabled"); - - pci_read_config_byte(bmide_dev, 0x40+2*pos, ®00); - pci_read_config_byte(bmide_dev, 0x41+2*pos, ®01); - pci_read_config_byte(bmide_dev, 0x44+2*pos, ®10); - pci_read_config_byte(bmide_dev, 0x45+2*pos, ®11); - -/* UDMA */ - if (chipset_family >= ATA_33) { - p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", - (reg01 & 0x80) ? "Enabled" : "Disabled", - (reg11 & 0x80) ? "Enabled" : "Disabled"); - - p += sprintf(p, " UDMA Cycle Time "); - switch(chipset_family) { - case ATA_33: p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break; - case ATA_66: - case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break; - case ATA_100: p += sprintf(p, cycle_time[reg01 & 0x0F]); break; - case ATA_133: - default: p += sprintf(p, "133+ ?"); break; - } - p += sprintf(p, " \t UDMA Cycle Time "); - switch(chipset_family) { - case ATA_33: p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break; - case ATA_66: - case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break; - case ATA_100: p += sprintf(p, cycle_time[reg11 & 0x0F]); break; - case ATA_133: - default: p += sprintf(p, "133+ ?"); break; - } - p += sprintf(p, "\n"); - } - -/* Data Active */ - p += sprintf(p, " Data Active Time "); - switch(chipset_family) { - case ATA_00: - case ATA_16: /* confirmed */ - case ATA_33: - case ATA_66: - case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break; - case ATA_100: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break; - case ATA_133: - default: p += sprintf(p, "133+ ?"); break; - } - p += sprintf(p, " \t Data Active Time "); - switch(chipset_family) { - case ATA_00: - case ATA_16: - case ATA_33: - case ATA_66: - case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break; - case ATA_100: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break; - case ATA_133: - default: p += sprintf(p, "133+ ?"); break; - } - p += sprintf(p, "\n"); - -/* Data Recovery */ - /* warning: may need (reg&0x07) for pre ATA66 chips */ - p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", - recovery_time[reg00 & 0x0f], recovery_time[reg10 & 0x0f]); - - return p; -} - -static char* get_masters_info(char* buffer) -{ - return get_drives_info(buffer, 0); -} - -static char* get_slaves_info(char* buffer) -{ - return get_drives_info(buffer, 1); -} - -/* Main get_info, called on /proc/ide/sis reads */ -static int sis_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - byte reg; - u16 reg2, reg3; - - p += sprintf(p, "\nSiS 5513 "); - switch(chipset_family) { - case ATA_00: p += sprintf(p, "Unknown???"); break; - case ATA_16: p += sprintf(p, "DMA 16"); break; - case ATA_33: p += sprintf(p, "Ultra 33"); break; - case ATA_66: p += sprintf(p, "Ultra 66"); break; - case ATA_100a: - case ATA_100: p += sprintf(p, "Ultra 100"); break; - case ATA_133: - default: p+= sprintf(p, "Ultra 133+"); break; - } - p += sprintf(p, " chipset\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - -/* Status */ - pci_read_config_byte(bmide_dev, 0x4a, ®); - p += sprintf(p, "Channel Status: "); - if (chipset_family < ATA_66) { - p += sprintf(p, "%s \t \t \t \t %s\n", - (reg & 0x04) ? "On" : "Off", - (reg & 0x02) ? "On" : "Off"); - } else { - p += sprintf(p, "%s \t \t \t \t %s \n", - (reg & 0x02) ? "On" : "Off", - (reg & 0x04) ? "On" : "Off"); - } - -/* Operation Mode */ - pci_read_config_byte(bmide_dev, 0x09, ®); - p += sprintf(p, "Operation Mode: %s \t \t \t %s \n", - (reg & 0x01) ? "Native" : "Compatible", - (reg & 0x04) ? "Native" : "Compatible"); - -/* 80-pin cable ? */ - if (chipset_family > ATA_33) { - pci_read_config_byte(bmide_dev, 0x48, ®); - p += sprintf(p, "Cable Type: %s \t \t \t %s\n", - (reg & 0x10) ? cable_type[1] : cable_type[0], - (reg & 0x20) ? cable_type[1] : cable_type[0]); - } - -/* Prefetch Count */ - pci_read_config_word(bmide_dev, 0x4c, ®2); - pci_read_config_word(bmide_dev, 0x4e, ®3); - p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n", - reg2, reg3); - - p = get_masters_info(p); - p = get_slaves_info(p); - - return p-buffer; -} - -byte sis_proc = 0; - -#endif - - static int sis5513_ratemask(struct ata_device *drive) { int map = 0; @@ -668,12 +466,14 @@ return !sis5513_tune_chipset(drive, mode); } -static int config_drive_xfer_rate(struct ata_device *drive) +static int sis5513_udma_setup(struct ata_device *drive) { struct hd_driveid *id = drive->id; int on = 0; int verbose = 1; + config_drive_art_rwp(drive); + config_art_rwp_pio(drive, 5); config_chipset_for_pio(drive, 5); if (id && (id->capability & 1) && drive->channel->autodma) { @@ -722,14 +522,6 @@ return 0; } - -static int sis5513_dmaproc(struct ata_device *drive) -{ - config_drive_art_rwp(drive); - config_art_rwp_pio(drive, 5); - - return config_drive_xfer_rate(drive); -} #endif /* Chip detection and general config */ @@ -800,14 +592,6 @@ case ATA_00: default: break; } - -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) - if (!sis_proc) { - sis_proc = 1; - bmide_dev = dev; - sis_display_info = &sis_get_info; - } -#endif } #ifdef DEBUG sis5513_load_verify_registers(dev, "pci_init_sis5513 end"); @@ -843,7 +627,7 @@ if (chipset_family > ATA_16) { hwif->autodma = noautodma ? 0 : 1; hwif->highmem = 1; - hwif->XXX_udma = sis5513_dmaproc; + hwif->udma_setup = sis5513_udma_setup; } else { #endif hwif->autodma = 0; diff -Nru a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c --- a/drivers/ide/sl82c105.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ide/sl82c105.c Sun Jun 2 18:44:57 2002 @@ -130,7 +130,7 @@ * Check to see if the drive and * chipset is capable of DMA mode */ -static int sl82c105_check_drive(struct ata_device *drive) +static int sl82c105_dma_setup(struct ata_device *drive) { int on = 0; @@ -173,15 +173,6 @@ } /* - * Our very own dmaproc. We need to intercept various calls - * to fix up the SL82C105 specific behaviour. - */ -static int sl82c105_dmaproc(struct ata_device *drive) -{ - return sl82c105_check_drive(drive); -} - -/* * The SL82C105 holds off all IDE interrupts while in DMA mode until * all DMA activity is completed. Sometimes this causes problems (eg, * when the drive wants to report an error condition). @@ -215,16 +206,10 @@ * The generic IDE core will have disabled the BMEN bit before this * function is called. */ -static int sl82c105_dma_read(struct ata_device *drive, struct request *rq) -{ - sl82c105_reset_host(drive->channel->pci_dev); - return udma_pci_read(drive, rq); -} - -static int sl82c105_dma_write(struct ata_device *drive, struct request *rq) +static int sl82c105_dma_init(struct ata_device *drive, struct request *rq) { sl82c105_reset_host(drive->channel->pci_dev); - return udma_pci_write(drive, rq); + return udma_pci_init(drive, rq); } static void sl82c105_timeout(struct ata_device *drive) @@ -354,12 +339,11 @@ ata_init_dma(ch, dma_base); if (bridge_rev <= 5) - ch->XXX_udma = NULL; + ch->udma_setup = NULL; else { - ch->XXX_udma = sl82c105_dmaproc; + ch->udma_setup = sl82c105_dma_setup; ch->udma_enable = sl82c105_dma_enable; - ch->udma_read = sl82c105_dma_read; - ch->udma_write = sl82c105_dma_write; + ch->udma_init = sl82c105_dma_init; ch->udma_timeout = sl82c105_timeout; ch->udma_irq_lost = sl82c105_lostirq; } diff -Nru a/drivers/ide/tcq.c b/drivers/ide/tcq.c --- a/drivers/ide/tcq.c Sun Jun 2 18:44:58 2002 +++ b/drivers/ide/tcq.c Sun Jun 2 18:44:58 2002 @@ -55,24 +55,14 @@ static ide_startstop_t ide_dmaq_intr(struct ata_device *drive, struct request *rq); static ide_startstop_t service(struct ata_device *drive, struct request *rq); -static inline void drive_ctl_nien(struct ata_device *drive, int set) -{ -#ifdef IDE_TCQ_NIEN - if (IDE_CONTROL_REG) { - int mask = set ? 0x02 : 0x00; - - OUT_BYTE(drive->ctl | mask, IDE_CONTROL_REG); - } -#endif -} - static ide_startstop_t tcq_nop_handler(struct ata_device *drive, struct request *rq) { struct ata_taskfile *args = rq->special; ide__sti(); - ide_end_drive_cmd(drive, rq, GET_STAT(), GET_ERR()); + ide_end_drive_cmd(drive, rq); kfree(args); + return ide_stopped; } @@ -128,18 +118,17 @@ BUG_ON(!rq); rq->special = args; - args->taskfile.command = WIN_NOP; + args->cmd = WIN_NOP; args->handler = tcq_nop_handler; args->command_type = IDE_DRIVE_TASK_NO_DATA; rq->rq_dev = mk_kdev(drive->channel->major, (drive->select.b.unit)<rq) == ide_started) return; @@ -246,13 +235,12 @@ /* * need to select the right drive first... */ - if (drive != drive->channel->drive) { - SELECT_DRIVE(drive->channel, drive); - udelay(10); - } - - drive_ctl_nien(drive, 1); + if (drive != drive->channel->drive) + ata_select(drive, 10); +#ifdef IDE_TCQ_NIEN + ata_irq_enable(drive, 0); +#endif /* * send SERVICE, wait 400ns, wait for BUSY_STAT to clear */ @@ -266,7 +254,9 @@ return ide_stopped; } - drive_ctl_nien(drive, 0); +#ifdef IDE_TCQ_NIEN + ata_irq_enable(drive, 1); +#endif /* * FIXME, invalidate queue @@ -309,14 +299,12 @@ static ide_startstop_t check_service(struct ata_device *drive, struct request *rq) { - u8 stat; - TCQ_PRINTK("%s: %s\n", drive->name, __FUNCTION__); if (!ata_pending_commands(drive)) return ide_stopped; - if ((stat = GET_STAT()) & SERVICE_STAT) + if (!ata_status(drive, 0, SERVICE_STAT)) return service(drive, rq); /* @@ -327,7 +315,7 @@ return ide_started; } -ide_startstop_t ide_dmaq_complete(struct ata_device *drive, struct request *rq, u8 stat) +static ide_startstop_t dmaq_complete(struct ata_device *drive, struct request *rq) { u8 dma_stat; @@ -339,9 +327,9 @@ /* * must be end of I/O, check status and complete as necessary */ - if (unlikely(!OK_STAT(stat, READY_STAT, drive->bad_wstat | DRQ_STAT))) { - printk(KERN_ERR "%s: %s: error status %x\n", __FUNCTION__, drive->name,stat); - ide_dump_status(drive, rq, __FUNCTION__, stat); + if (!ata_status(drive, READY_STAT, drive->bad_wstat | DRQ_STAT)) { + printk(KERN_ERR "%s: %s: error status %x\n", __FUNCTION__, drive->name, drive->status); + ide_dump_status(drive, rq, __FUNCTION__, drive->status); tcq_invalidate_queue(drive); return ide_stopped; @@ -360,7 +348,7 @@ } /* - * intr handler for queued dma operations. this can be entered for two + * Interrupt handler for queued dma operations. this can be entered for two * reasons: * * 1) device has completed dma transfer @@ -371,26 +359,28 @@ */ static ide_startstop_t ide_dmaq_intr(struct ata_device *drive, struct request *rq) { - u8 stat = GET_STAT(); + int ok; - TCQ_PRINTK("%s: stat=%x\n", __FUNCTION__, stat); + ok = !ata_status(drive, 0, SERVICE_STAT); + TCQ_PRINTK("%s: stat=%x\n", __FUNCTION__, drive->status); /* - * if a command completion interrupt is pending, do that first and - * check service afterwards + * If a command completion interrupt is pending, do that first and + * check service afterwards. */ if (rq) - return ide_dmaq_complete(drive, rq, stat); + return dmaq_complete(drive, rq); /* * service interrupt */ - if (stat & SERVICE_STAT) { - TCQ_PRINTK("%s: SERV (stat=%x)\n", __FUNCTION__, stat); + if (ok) { + TCQ_PRINTK("%s: SERV (stat=%x)\n", __FUNCTION__, drive->status); return service(drive, rq); } - printk("%s: stat=%x, not expected\n", __FUNCTION__, stat); + printk("%s: stat=%x, not expected\n", __FUNCTION__, drive->status); + return check_service(drive, rq); } @@ -417,7 +407,7 @@ memset(&args, 0, sizeof(args)); args.taskfile.feature = 0x01; - args.taskfile.command = WIN_NOP; + args.cmd = WIN_NOP; ide_cmd_type_parser(&args); /* @@ -452,7 +442,7 @@ memset(&args, 0, sizeof(args)); args.taskfile.feature = SETFEATURES_EN_WCACHE; - args.taskfile.command = WIN_SETFEATURES; + args.cmd = WIN_SETFEATURES; ide_cmd_type_parser(&args); if (ide_raw_taskfile(drive, &args)) { @@ -466,7 +456,7 @@ */ memset(&args, 0, sizeof(args)); args.taskfile.feature = SETFEATURES_DIS_RI; - args.taskfile.command = WIN_SETFEATURES; + args.cmd = WIN_SETFEATURES; ide_cmd_type_parser(&args); if (ide_raw_taskfile(drive, &args)) { @@ -480,7 +470,7 @@ */ memset(&args, 0, sizeof(args)); args.taskfile.feature = SETFEATURES_EN_SI; - args.taskfile.command = WIN_SETFEATURES; + args.cmd = WIN_SETFEATURES; ide_cmd_type_parser(&args); if (ide_raw_taskfile(drive, &args)) { @@ -494,19 +484,19 @@ static int tcq_wait_dataphase(struct ata_device *drive) { - u8 stat; int i; - while ((stat = GET_STAT()) & BUSY_STAT) + while (!ata_status(drive, 0, BUSY_STAT)) udelay(10); - if (OK_STAT(stat, READY_STAT | DRQ_STAT, drive->bad_wstat)) + if (ata_status(drive, READY_STAT | DRQ_STAT, drive->bad_wstat)) return 0; i = 0; udelay(1); - while (!OK_STAT(GET_STAT(), READY_STAT | DRQ_STAT, drive->bad_wstat)) { - if (unlikely(i++ > IDE_TCQ_WAIT)) + while (!ata_status(drive, READY_STAT | DRQ_STAT, drive->bad_wstat)) { + ++i; + if (i > IDE_TCQ_WAIT) return 1; udelay(10); @@ -560,9 +550,11 @@ * set nIEN, tag start operation will enable again when * it is safe */ - drive_ctl_nien(drive, 1); +#ifdef IDE_TCQ_NIEN + ata_irq_enable(drive, 0); +#endif - OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG); + OUT_BYTE(args->cmd, IDE_COMMAND_REG); if (wait_altstat(drive, &stat, BUSY_STAT)) { ide_dump_status(drive, rq, "queued start", stat); @@ -570,7 +562,9 @@ return ide_stopped; } - drive_ctl_nien(drive, 0); +#ifdef IDE_TCQ_NIEN + ata_irq_enable(drive, 1); +#endif if (stat & ERR_STAT) { ide_dump_status(drive, rq, "tcq_start", stat); @@ -588,7 +582,7 @@ TCQ_PRINTK("REL in queued_start\n"); - if ((stat = GET_STAT()) & SERVICE_STAT) + if (!ata_status(drive, 0, SERVICE_STAT)) return service(drive, rq); return ide_released; diff -Nru a/drivers/ide/trm290.c b/drivers/ide/trm290.c --- a/drivers/ide/trm290.c Sun Jun 2 18:44:56 2002 +++ b/drivers/ide/trm290.c Sun Jun 2 18:44:56 2002 @@ -191,10 +191,18 @@ return (inw(ch->dma_base + 2) != 0x00ff); } -static int do_udma(unsigned int reading, struct ata_device *drive, struct request *rq) +static int trm290_udma_init(struct ata_device *drive, struct request *rq) { struct ata_channel *ch = drive->channel; - unsigned int count, writing; + unsigned int count; + int writing; + int reading; + + + if (rq_data_dir(rq) == READ) + reading = 1; + else + reading = 0; if (!reading) { reading = 0; @@ -222,30 +230,20 @@ if (drive->type != ATA_DISK) return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); + ide_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); return 0; } -static int trm290_udma_read(struct ata_device *drive, struct request *rq) -{ - return do_udma(1, drive, rq); -} - -static int trm290_udma_write(struct ata_device *drive, struct request *rq) -{ - return do_udma(0, drive, rq); -} - static int trm290_udma_irq_status(struct ata_device *drive) { return (inw(drive->channel->dma_base + 2) == 0x00ff); } -static int trm290_dmaproc(struct ata_device *drive) +static int trm290_udma_setup(struct ata_device *drive) { - return XXX_ide_dmaproc(drive); + return udma_pci_setup(drive); } #endif @@ -301,10 +299,9 @@ #ifdef CONFIG_BLK_DEV_IDEDMA hwif->udma_start = trm290_udma_start; hwif->udma_stop = trm290_udma_stop; - hwif->udma_read = trm290_udma_read; - hwif->udma_write = trm290_udma_write; + hwif->udma_init = trm290_udma_init; hwif->udma_irq_status = trm290_udma_irq_status; - hwif->XXX_udma = trm290_dmaproc; + hwif->udma_setup = trm290_udma_setup; #endif hwif->selectproc = &trm290_selectproc; diff -Nru a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c --- a/drivers/ide/via82cxxx.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ide/via82cxxx.c Sun Jun 2 18:44:57 2002 @@ -135,139 +135,6 @@ static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" }; /* - * VIA /proc entry. - */ - -#if 0 && defined(CONFIG_PROC_FS) - -#include -#include - -int via_proc, via_base; -static struct pci_dev *bmide_dev, *isa_dev; -extern int (*via_display_info)(char *, char **, off_t, int); /* ide-proc.c */ - -static char *via_control3[] = { "No limit", "64", "128", "192" }; - -#define via_print(format, arg...) p += sprintf(p, format "\n" , ## arg) -#define via_print_drive(name, format, arg...)\ - p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n"); - -static int via_get_info(char *buffer, char **addr, off_t offset, int count) -{ - int speed[4], cycle[4], setup[4], active[4], recover[4], den[4], - uen[4], udma[4], umul[4], active8b[4], recover8b[4]; - struct pci_dev *dev = bmide_dev; - unsigned int v, u, i; - unsigned short c, w; - unsigned char t, x; - char *p = buffer; - - via_print("----------VIA BusMastering IDE Configuration----------------"); - - via_print("Driver Version: 3.34"); - via_print("South Bridge: VIA %s", via_config->name); - - pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t); - pci_read_config_byte(dev, PCI_REVISION_ID, &x); - via_print("Revision: ISA %#x IDE %#x", t, x); - via_print("Highest DMA rate: %s", via_dma[via_config->flags & VIA_UDMA]); - - via_print("BM-DMA base: %#x", via_base); - via_print("PCI clock: %d.%dMHz", system_bus_speed / 1000, system_bus_speed / 100 % 10); - - pci_read_config_byte(dev, VIA_MISC_1, &t); - via_print("Master Read Cycle IRDY: %dws", (t & 64) >> 6); - via_print("Master Write Cycle IRDY: %dws", (t & 32) >> 5); - via_print("BM IDE Status Register Read Retry: %s", (t & 8) ? "yes" : "no"); - - pci_read_config_byte(dev, VIA_MISC_3, &t); - via_print("Max DRDY Pulse Width: %s%s", via_control3[(t & 0x03)], (t & 0x03) ? " PCI clocks" : ""); - - via_print("-----------------------Primary IDE-------Secondary IDE------"); - via_print("Read DMA FIFO flush: %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x40) ? "yes" : "no"); - via_print("End Sector FIFO flush: %10s%20s", (t & 0x20) ? "yes" : "no", (t & 0x10) ? "yes" : "no"); - - pci_read_config_byte(dev, VIA_IDE_CONFIG, &t); - via_print("Prefetch Buffer: %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x20) ? "yes" : "no"); - via_print("Post Write Buffer: %10s%20s", (t & 0x40) ? "yes" : "no", (t & 0x10) ? "yes" : "no"); - - pci_read_config_byte(dev, VIA_IDE_ENABLE, &t); - via_print("Enabled: %10s%20s", (t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no"); - - c = inb(via_base + 0x02) | (inb(via_base + 0x0a) << 8); - via_print("Simplex only: %10s%20s", (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no"); - - via_print("Cable Type: %10s%20s", (via_80w & 1) ? "80w" : "40w", (via_80w & 2) ? "80w" : "40w"); - - via_print("-------------------drive0----drive1----drive2----drive3-----"); - - pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); - pci_read_config_dword(dev, VIA_DRIVE_TIMING, &v); - pci_read_config_word(dev, VIA_8BIT_TIMING, &w); - - if (via_config->flags & VIA_UDMA) - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); - else u = 0; - - for (i = 0; i < 4; i++) { - - setup[i] = ((t >> ((3 - i) << 1)) & 0x3) + 1; - recover8b[i] = ((w >> ((1 - (i >> 1)) << 3)) & 0xf) + 1; - active8b[i] = ((w >> (((1 - (i >> 1)) << 3) + 4)) & 0xf) + 1; - active[i] = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1; - recover[i] = ((v >> ((3 - i) << 3)) & 0xf) + 1; - udma[i] = ((u >> ((3 - i) << 3)) & 0x7) + 2; - umul[i] = ((u >> (((3 - i) & 2) << 3)) & 0x8) ? 1 : 2; - uen[i] = ((u >> ((3 - i) << 3)) & 0x20); - den[i] = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2)); - - speed[i] = 2 * system_bus_speed / (active[i] + recover[i]); - cycle[i] = 1000000 * (active[i] + recover[i]) / system_bus_speed; - - if (!uen[i] || !den[i]) - continue; - - switch (via_config->flags & VIA_UDMA) { - - case VIA_UDMA_33: - speed[i] = 2 * system_bus_speed / udma[i]; - cycle[i] = 1000000 * udma[i] / system_bus_speed; - break; - - case VIA_UDMA_66: - speed[i] = 4 * system_bus_speed / (udma[i] * umul[i]); - cycle[i] = 500000 * (udma[i] * umul[i]) / system_bus_speed; - break; - - case VIA_UDMA_100: - speed[i] = 6 * system_bus_speed / udma[i]; - cycle[i] = 333333 * udma[i] / system_bus_speed; - break; - - case VIA_UDMA_133: - speed[i] = 8 * system_bus_speed / udma[i]; - cycle[i] = 250000 * udma[i] / system_bus_speed; - break; - } - } - - via_print_drive("Transfer Mode: ", "%10s", den[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO"); - - via_print_drive("Address Setup: ", "%8dns", 1000000 * setup[i] / system_bus_speed); - via_print_drive("Cmd Active: ", "%8dns", 1000000 * active8b[i] / system_bus_speed); - via_print_drive("Cmd Recovery: ", "%8dns", 1000000 * recover8b[i] / system_bus_speed); - via_print_drive("Data Active: ", "%8dns", 1000000 * active[i] / system_bus_speed); - via_print_drive("Data Recovery: ", "%8dns", 1000000 * recover[i] / system_bus_speed); - via_print_drive("Cycle Time: ", "%8dns", cycle[i]); - via_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 1000, speed[i] / 100 % 10); - - return p - buffer; /* hoping it is less than 4K... */ -} - -#endif - -/* * via_set_speed() writes timing values to the chipset registers */ @@ -356,7 +223,7 @@ } #ifdef CONFIG_BLK_DEV_IDEDMA -static int via82cxxx_dmaproc(struct ata_device *drive) +static int via82cxxx_udma_setup(struct ata_device *drive) { short w80 = drive->channel->udma_four; @@ -501,7 +368,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { hwif->highmem = 1; - hwif->XXX_udma = &via82cxxx_dmaproc; + hwif->udma_setup = via82cxxx_udma_setup; # ifdef CONFIG_IDEDMA_AUTO if (!noautodma) hwif->autodma = 1; diff -Nru a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c --- a/drivers/ieee1394/pcilynx.c Sun Jun 2 18:44:57 2002 +++ b/drivers/ieee1394/pcilynx.c Sun Jun 2 18:44:57 2002 @@ -880,7 +880,7 @@ retval = copy_to_user(buffer, md->lynx->mem_dma_buffer, count); up(&md->lynx->mem_dma_mutex); - if (retval < 0) return retval; + if (retval) return -EFAULT; *offset += count; return count; } diff -Nru a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c --- a/drivers/isdn/hisax/avm_a1.c Sun Jun 2 18:44:56 2002 +++ b/drivers/isdn/hisax/avm_a1.c Sun Jun 2 18:44:56 2002 @@ -196,17 +196,15 @@ cs->hw.avm.hscxfifo[0] = card->para[1]; cs->hw.avm.hscxfifo[1] = card->para[1] + 0x800; cs->irq = card->para[0]; - if (check_region((cs->hw.avm.cfg_reg), 8)) { + if (!request_region(cs->hw.avm.cfg_reg, 8, "avm cfg")) { printk(KERN_WARNING "HiSax: %s config port %x-%x already in use\n", CardType[card->typ], cs->hw.avm.cfg_reg, cs->hw.avm.cfg_reg + 8); return (0); - } else { - request_region(cs->hw.avm.cfg_reg, 8, "avm cfg"); } - if (check_region((cs->hw.avm.isac + 32), 32)) { + if (!request_region(cs->hw.avm.isac + 32, 32, "HiSax isac")) { printk(KERN_WARNING "HiSax: %s isac ports %x-%x already in use\n", CardType[cs->typ], @@ -214,20 +212,16 @@ cs->hw.avm.isac + 64); release_ioregs(cs, 0); return (0); - } else { - request_region(cs->hw.avm.isac + 32, 32, "HiSax isac"); } - if (check_region((cs->hw.avm.isacfifo), 1)) { + if (!request_region(cs->hw.avm.isacfifo, 1, "HiSax isac fifo")) { printk(KERN_WARNING "HiSax: %s isac fifo port %x already in use\n", CardType[cs->typ], cs->hw.avm.isacfifo); release_ioregs(cs, 1); return (0); - } else { - request_region(cs->hw.avm.isacfifo, 1, "HiSax isac fifo"); } - if (check_region((cs->hw.avm.hscx[0]) + 32, 32)) { + if (!request_region(cs->hw.avm.hscx[0] + 32, 32, "HiSax hscx A")) { printk(KERN_WARNING "HiSax: %s hscx A ports %x-%x already in use\n", CardType[cs->typ], @@ -235,20 +229,16 @@ cs->hw.avm.hscx[0] + 64); release_ioregs(cs, 3); return (0); - } else { - request_region(cs->hw.avm.hscx[0] + 32, 32, "HiSax hscx A"); } - if (check_region(cs->hw.avm.hscxfifo[0], 1)) { + if (!request_region(cs->hw.avm.hscxfifo[0], 1, "HiSax hscx A fifo")) { printk(KERN_WARNING "HiSax: %s hscx A fifo port %x already in use\n", CardType[cs->typ], cs->hw.avm.hscxfifo[0]); release_ioregs(cs, 7); return (0); - } else { - request_region(cs->hw.avm.hscxfifo[0], 1, "HiSax hscx A fifo"); } - if (check_region(cs->hw.avm.hscx[1] + 32, 32)) { + if (!request_region(cs->hw.avm.hscx[1] + 32, 32, "HiSax hscx B")) { printk(KERN_WARNING "HiSax: %s hscx B ports %x-%x already in use\n", CardType[cs->typ], @@ -256,18 +246,14 @@ cs->hw.avm.hscx[1] + 64); release_ioregs(cs, 0xf); return (0); - } else { - request_region(cs->hw.avm.hscx[1] + 32, 32, "HiSax hscx B"); } - if (check_region(cs->hw.avm.hscxfifo[1], 1)) { + if (!request_region(cs->hw.avm.hscxfifo[1], 1, "HiSax hscx B fifo")) { printk(KERN_WARNING "HiSax: %s hscx B fifo port %x already in use\n", CardType[cs->typ], cs->hw.avm.hscxfifo[1]); release_ioregs(cs, 0x1f); return (0); - } else { - request_region(cs->hw.avm.hscxfifo[1], 1, "HiSax hscx B fifo"); } save_flags(flags); byteout(cs->hw.avm.cfg_reg, 0x0); diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c --- a/drivers/isdn/hisax/elsa.c Sun Jun 2 18:44:56 2002 +++ b/drivers/isdn/hisax/elsa.c Sun Jun 2 18:44:56 2002 @@ -598,15 +598,13 @@ Elsa_Types[cs->subtyp], cs->hw.elsa.base+8); release_region(cs->hw.elsa.base, 8); - if (check_region(cs->hw.elsa.base, 16)) { + if (!request_region(cs->hw.elsa.base, 16,"elsa isdn modem")) { printk(KERN_WARNING "HiSax: %s config port %lx-%lx already in use\n", Elsa_Types[cs->subtyp], cs->hw.elsa.base + 8, cs->hw.elsa.base + 16); - } else - request_region(cs->hw.elsa.base, 16, - "elsa isdn modem"); + } } else if (cs->subtyp==ELSA_PCC16) { cs->subtyp = ELSA_PCF; printk(KERN_INFO @@ -614,15 +612,13 @@ Elsa_Types[cs->subtyp], cs->hw.elsa.base+8); release_region(cs->hw.elsa.base, 8); - if (check_region(cs->hw.elsa.base, 16)) { + if (!request_region(cs->hw.elsa.base, 16,"elsa isdn modem")) { printk(KERN_WARNING "HiSax: %s config port %lx-%lx already in use\n", Elsa_Types[cs->subtyp], cs->hw.elsa.base + 8, cs->hw.elsa.base + 16); - } else - request_region(cs->hw.elsa.base, 16, - "elsa isdn modem"); + } } else printk(KERN_INFO "Elsa: %s detected modem at 0x%lx\n", @@ -1066,18 +1062,18 @@ /* In case of the elsa pcmcia card, this region is in use, reserved for us by the card manager. So we do not check it here, it would fail. */ - if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA && check_region(cs->hw.elsa.base, bytecnt)) { - printk(KERN_WARNING - "HiSax: %s config port %#lx-%#lx already in use\n", - CardType[card->typ], - cs->hw.elsa.base, - cs->hw.elsa.base + bytecnt); - return (0); - } else { - request_region(cs->hw.elsa.base, bytecnt, "elsa isdn"); - } + if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA) + if (!request_region(cs->hw.elsa.base, bytecnt, "elsa isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %#lx-%#lx already in use\n", + CardType[card->typ], + cs->hw.elsa.base, + cs->hw.elsa.base + bytecnt); + return (0); + } + if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) { - if (check_region(cs->hw.elsa.cfg, 0x80)) { + if (!pci_request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) { printk(KERN_WARNING "HiSax: %s pci port %x-%x already in use\n", CardType[card->typ], @@ -1085,8 +1081,6 @@ cs->hw.elsa.cfg + 0x80); release_region(cs->hw.elsa.base, bytecnt); return (0); - } else { - request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci"); } } #if ARCOFI_USE diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c --- a/drivers/isdn/hisax/gazel.c Sun Jun 2 18:44:56 2002 +++ b/drivers/isdn/hisax/gazel.c Sun Jun 2 18:44:56 2002 @@ -451,42 +451,45 @@ case R647: base = cs->hw.gazel.hscx[0]; for (i = 0x0000; i < 0xC000; i += 0x1000) { - if (check_region(adr = (i + base), len = 16)) + if (!request_region(adr = (i + base), len = 16, "gazel")) { + int j; + + for (j = 0x0000; j < i; j += 0x1000) + release_region ((j + base), len); goto error; + } } - if (check_region(adr = (0xC000 + base), len = 1)) + if (!request_region(adr = (0xC000 + base), len = 1, "gazel")) { + for (i = 0x0000; i < 0xC000; i += 0x1000) + release_region ((i + base), 16); goto error; - - for (i = 0x0000; i < 0xC000; i += 0x1000) - request_region(i + base, 16, "gazel"); - request_region(0xC000 + base, 1, "gazel"); + } break; case R685: - if (check_region(adr = cs->hw.gazel.hscx[0], len = 0x100)) + if (!request_region(adr = cs->hw.gazel.hscx[0], len = 0x100, "gazel")) goto error; - if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80)) + if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) { + release_region (cs->hw.gazel.hscx[0], 0x100); goto error; + } - request_region(cs->hw.gazel.hscx[0], 0x100, "gazel"); - request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel"); break; case R753: - if (check_region(adr = cs->hw.gazel.ipac, len = 0x8)) + if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel")) goto error; - if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80)) + if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) { + release_region (cs->hw.gazel.ipac, 0x8); goto error; + } - request_region(cs->hw.gazel.ipac, 0x8, "gazel"); - request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel"); break; case R742: - if (check_region(adr = cs->hw.gazel.ipac, len = 0x8)) + if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel")) goto error; - request_region(cs->hw.gazel.ipac, 0x8, "gazel"); break; } diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c --- a/drivers/isdn/hisax/hisax_fcpcipnp.c Sun Jun 2 18:44:56 2002 +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c Sun Jun 2 18:44:56 2002 @@ -370,7 +370,7 @@ unsigned long flags; unsigned char *p; - DBG(0x40, ""); + DBG(0x40, "hdlc_fill_fifo"); if (skb->len == 0) BUG(); diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c --- a/drivers/isdn/hisax/niccy.c Sun Jun 2 18:44:57 2002 +++ b/drivers/isdn/hisax/niccy.c Sun Jun 2 18:44:57 2002 @@ -258,16 +258,15 @@ cs->hw.niccy.cfg_reg = 0; cs->subtyp = NICCY_PNP; cs->irq = card->para[0]; - if (check_region((cs->hw.niccy.isac), 2)) { + if (!request_region(cs->hw.niccy.isac, 2, "niccy data")) { printk(KERN_WARNING "HiSax: %s data port %x-%x already in use\n", CardType[card->typ], cs->hw.niccy.isac, cs->hw.niccy.isac + 1); return (0); - } else - request_region(cs->hw.niccy.isac, 2, "niccy data"); - if (check_region((cs->hw.niccy.isac_ale), 2)) { + } + if (!request_region(cs->hw.niccy.isac_ale, 2, "niccy addr")) { printk(KERN_WARNING "HiSax: %s address port %x-%x already in use\n", CardType[card->typ], @@ -275,8 +274,7 @@ cs->hw.niccy.isac_ale + 1); release_region(cs->hw.niccy.isac, 2); return (0); - } else - request_region(cs->hw.niccy.isac_ale, 2, "niccy addr"); + } } else { #if CONFIG_PCI u_int pci_ioaddr; @@ -315,16 +313,15 @@ cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA; cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR; - if (check_region((cs->hw.niccy.isac), 4)) { + if (!request_region(cs->hw.niccy.isac, 4, "niccy")) { printk(KERN_WARNING "HiSax: %s data port %x-%x already in use\n", CardType[card->typ], cs->hw.niccy.isac, cs->hw.niccy.isac + 4); return (0); - } else - request_region(cs->hw.niccy.isac, 4, "niccy"); - if (check_region(cs->hw.niccy.cfg_reg, 0x40)) { + } + if (!request_region(cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) { printk(KERN_WARNING "HiSax: %s pci port %x-%x already in use\n", CardType[card->typ], @@ -332,8 +329,6 @@ cs->hw.niccy.cfg_reg + 0x40); release_region(cs->hw.niccy.isac, 4); return (0); - } else { - request_region(cs->hw.niccy.cfg_reg, 0x40, "niccy pci"); } #else printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n"); diff -Nru a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c --- a/drivers/isdn/hisax/teles3.c Sun Jun 2 18:44:57 2002 +++ b/drivers/isdn/hisax/teles3.c Sun Jun 2 18:44:57 2002 @@ -300,39 +300,36 @@ cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { - if (check_region((cs->hw.teles3.hscx[1]), 96 )) { + if (!request_region(cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA")) { printk(KERN_WARNING "HiSax: %s ports %x-%x already in use\n", CardType[cs->typ], cs->hw.teles3.hscx[1], cs->hw.teles3.hscx[1] + 96); return (0); - } else - request_region(cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA"); + } } else { if (cs->hw.teles3.cfg_reg) { if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { - if (check_region((cs->hw.teles3.cfg_reg), 1)) { + if (!request_region(cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) { printk(KERN_WARNING "HiSax: %s config port %x already in use\n", CardType[card->typ], cs->hw.teles3.cfg_reg); return (0); - } else - request_region(cs->hw.teles3.cfg_reg, 1, "teles3 cfg"); + } } else { - if (check_region((cs->hw.teles3.cfg_reg), 8)) { + if (!request_region(cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) { printk(KERN_WARNING "HiSax: %s config port %x-%x already in use\n", CardType[card->typ], cs->hw.teles3.cfg_reg, cs->hw.teles3.cfg_reg + 8); return (0); - } else - request_region(cs->hw.teles3.cfg_reg, 8, "teles3 cfg"); + } } } - if (check_region((cs->hw.teles3.isac + 32), 32)) { + if (!request_region(cs->hw.teles3.isac + 32, 32, "HiSax isac")) { printk(KERN_WARNING "HiSax: %s isac ports %x-%x already in use\n", CardType[cs->typ], @@ -346,9 +343,8 @@ } } return (0); - } else - request_region(cs->hw.teles3.isac + 32, 32, "HiSax isac"); - if (check_region((cs->hw.teles3.hscx[0] + 32), 32)) { + } + if (!request_region(cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A")) { printk(KERN_WARNING "HiSax: %s hscx A ports %x-%x already in use\n", CardType[cs->typ], @@ -363,9 +359,8 @@ } release_ioregs(cs, 1); return (0); - } else - request_region(cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A"); - if (check_region((cs->hw.teles3.hscx[1] + 32), 32)) { + } + if (!request_region(cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B")) { printk(KERN_WARNING "HiSax: %s hscx B ports %x-%x already in use\n", CardType[cs->typ], @@ -380,8 +375,7 @@ } release_ioregs(cs, 3); return (0); - } else - request_region(cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B"); + } } if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) { if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) { diff -Nru a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c --- a/drivers/media/video/video-buf.c Sun Jun 2 18:44:57 2002 +++ b/drivers/media/video/video-buf.c Sun Jun 2 18:44:57 2002 @@ -365,7 +365,7 @@ page = alloc_page(GFP_USER); if (!page) return NOPAGE_OOM; - clear_user_page(page_address(page), vaddr); + clear_user_page(page_address(page), vaddr, page); return page; } diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c --- a/drivers/mtd/nftlcore.c Sun Jun 2 18:44:56 2002 +++ b/drivers/mtd/nftlcore.c Sun Jun 2 18:44:56 2002 @@ -846,11 +846,11 @@ /* We can do this because the generic code knows not to touch the request at the head of the queue */ - spin_unlock_irq(&QUEUE->queue_lock); + spin_unlock_irq(QUEUE->queue_lock); DEBUG(MTD_DEBUG_LEVEL2, "NFTL_request\n"); DEBUG(MTD_DEBUG_LEVEL3, - "NFTL %s request, from sector 0x%04lx for 0x%04lx sectors\n", + "NFTL %s request, from sector 0x%04lx for %d sectors\n", (req->cmd == READ) ? "Read " : "Write", req->sector, req->current_nr_sectors); @@ -899,7 +899,7 @@ DEBUG(MTD_DEBUG_LEVEL2,"NFTL read request completed OK\n"); up(&nftl->mutex); goto repeat; - } else if (req->cmd == WRITE) { + } else if (rq_data_dir(req) == WRITE) { DEBUG(MTD_DEBUG_LEVEL2, "NFTL write request of 0x%x sectors @ %x " "(req->nr_sectors == %lx)\n", nsect, block, req->nr_sectors); @@ -927,7 +927,7 @@ } repeat: DEBUG(MTD_DEBUG_LEVEL3, "end_request(%d)\n", res); - spin_lock_irq(&QUEUE->queue_lock); + spin_lock_irq(QUEUE->queue_lock); end_request(res); } } @@ -1015,10 +1015,10 @@ }; extern char nftlmountrev[]; +static spinlock_t nftl_lock = SPIN_LOCK_UNLOCKED; int __init init_nftl(void) { - int i; #ifdef PRERELEASE printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.82 $, nftlmount.c %s\n", nftlmountrev); @@ -1028,7 +1028,7 @@ printk("unable to register NFTL block device on major %d\n", MAJOR_NR); return -EBUSY; } else { - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request); + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request, &nftl_lock); add_gendisk(&nftl_gendisk); } diff -Nru a/drivers/net/3c501.c b/drivers/net/3c501.c --- a/drivers/net/3c501.c Sun Jun 2 18:44:56 2002 +++ b/drivers/net/3c501.c Sun Jun 2 18:44:56 2002 @@ -338,7 +338,7 @@ if (autoirq == 0) { - printk("%s probe at %#x failed to detect IRQ line.\n", + printk(KERN_WARNING "%s probe at %#x failed to detect IRQ line.\n", mname, ioaddr); release_region(ioaddr, EL1_IO_EXTENT); return -EAGAIN; @@ -362,7 +362,7 @@ #endif if (el_debug) - printk("%s", version); + printk(KERN_DEBUG "%s", version); /* * Initialize the device structure. @@ -421,7 +421,7 @@ unsigned long flags; if (el_debug > 2) - printk("%s: Doing el_open()...", dev->name); + printk(KERN_DEBUG "%s: Doing el_open()...", dev->name); if ((retval = request_irq(dev->irq, &el_interrupt, 0, dev->name, dev))) return retval; @@ -545,13 +545,13 @@ lp->loading=0; dev->trans_start = jiffies; if (el_debug > 2) - printk(" queued xmit.\n"); + printk(KERN_DEBUG " queued xmit.\n"); dev_kfree_skb (skb); return 0; } /* A receive upset our load, despite our best efforts */ if(el_debug>2) - printk("%s: burped during tx load.\n", dev->name); + printk(KERN_DEBUG "%s: burped during tx load.\n", dev->name); spin_lock_irqsave(&lp->lock, flags); } while(1); @@ -626,7 +626,7 @@ if(el_debug > 2) { printk(KERN_DEBUG "%s: Interrupt while loading [", dev->name); - printk(" txsr=%02x gp=%04x rp=%04x]\n", txsr, inw(GP_LOW),inw(RX_LOW)); + printk(KERN_DEBUG " txsr=%02x gp=%04x rp=%04x]\n", txsr, inw(GP_LOW),inw(RX_LOW)); } lp->loading=2; /* Force a reload */ spin_unlock(&lp->lock); @@ -643,7 +643,7 @@ * reset immediately ? */ if(el_debug>1) - printk("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x" + printk(KERN_DEBUG "%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x" " gp=%03x rp=%03x.\n", dev->name, txsr, axsr, inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR)); lp->txing = 0; @@ -655,7 +655,7 @@ * Timed out */ if (el_debug) - printk("%s: Transmit failed 16 times, Ethernet jammed?\n",dev->name); + printk (KERN_DEBUG "%s: Transmit failed 16 times, Ethernet jammed?\n",dev->name); outb(AX_SYS, AX_CMD); lp->txing = 0; lp->stats.tx_aborted_errors++; @@ -668,7 +668,7 @@ */ if (el_debug > 6) - printk(" retransmitting after a collision.\n"); + printk(KERN_DEBUG " retransmitting after a collision.\n"); /* * Poor little chip can't reset its own start pointer */ @@ -687,7 +687,7 @@ */ lp->stats.tx_packets++; if (el_debug > 6) - printk(" Tx succeeded %s\n", + printk(KERN_DEBUG " Tx succeeded %s\n", (txsr & TX_RDY) ? "." : "but tx is busy!"); /* * This is safe the interrupt is atomic WRT itself. @@ -705,7 +705,7 @@ int rxsr = inb(RX_STATUS); if (el_debug > 5) - printk(" rxsr=%02x txsr=%02x rp=%04x", rxsr, inb(TX_STATUS),inw(RX_LOW)); + printk(KERN_DEBUG " rxsr=%02x txsr=%02x rp=%04x", rxsr, inb(TX_STATUS),inw(RX_LOW)); /* * Just reading rx_status fixes most errors. */ @@ -715,7 +715,7 @@ { /* Handled to avoid board lock-up. */ lp->stats.rx_length_errors++; if (el_debug > 5) - printk(" runt.\n"); + printk(KERN_DEBUG " runt.\n"); } else if (rxsr & RX_GOOD) { @@ -730,12 +730,12 @@ * Nothing? Something is broken! */ if (el_debug > 2) - printk("%s: No packet seen, rxsr=%02x **resetting 3c501***\n", + printk(KERN_DEBUG "%s: No packet seen, rxsr=%02x **resetting 3c501***\n", dev->name, rxsr); el_reset(dev); } if (el_debug > 3) - printk(".\n"); + printk(KERN_DEBUG ".\n"); } /* @@ -771,12 +771,12 @@ pkt_len = inw(RX_LOW); if (el_debug > 4) - printk(" el_receive %d.\n", pkt_len); + printk(KERN_DEBUG " el_receive %d.\n", pkt_len); if ((pkt_len < 60) || (pkt_len > 1536)) { if (el_debug) - printk("%s: bogus packet, length=%d\n", dev->name, pkt_len); + printk(KERN_DEBUG "%s: bogus packet, length=%d\n", dev->name, pkt_len); lp->stats.rx_over_errors++; return; } @@ -795,7 +795,7 @@ outw(0x00, GP_LOW); if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet.\n", dev->name); + printk(KERN_INFO "%s: Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++; return; } @@ -833,7 +833,7 @@ int ioaddr = dev->base_addr; if (el_debug> 2) - printk("3c501 reset..."); + printk(KERN_INFO "3c501 reset..."); outb(AX_RESET, AX_CMD); /* Reset the chip */ outb(AX_LOOP, AX_CMD); /* Aux control, irq and loopback enabled */ { @@ -866,7 +866,7 @@ int ioaddr = dev->base_addr; if (el_debug > 2) - printk("%s: Shutting down Ethernet card at %#x.\n", dev->name, ioaddr); + printk(KERN_INFO "%s: Shutting down Ethernet card at %#x.\n", dev->name, ioaddr); netif_stop_queue(dev); diff -Nru a/drivers/net/Config.help b/drivers/net/Config.help --- a/drivers/net/Config.help Sun Jun 2 18:44:56 2002 +++ b/drivers/net/Config.help Sun Jun 2 18:44:56 2002 @@ -828,18 +828,23 @@ This driver supports Intel(R) PRO/1000 gigabit ethernet family of adapters, which includes: - Controller Adapter Name Board IDs - ---------- ------------ --------- - 82542 PRO/1000 Gigabit Server Adapter 700262-xxx, - 717037-xxx - 82543 PRO/1000 F Server Adapter 738640-xxx, - A38888-xxx, - A06512-xxx - 82543 PRO/1000 T Server Adapter A19845-xxx, - A33948-xxx - 82544 PRO/1000 XT Server Adapter A51580-xxx - 82544 PRO/1000 XF Server Adapter A50484-xxx - 82544 PRO/1000 T Desktop Adapter A62947-xxx + Controller Adapter Name Board IDs + ---------- ------------ --------- + 82542 PRO/1000 Gigabit Server Adapter 700262-xxx, + 717037-xxx + 82543 PRO/1000 F Server Adapter 738640-xxx, + A38888-xxx + 82543 PRO/1000 T Server Adapter A19845-xxx, + A33948-xxx + 82544 PRO/1000 XT Server Adapter A51580-xxx + 82544 PRO/1000 XF Server Adapter A50484-xxx + 82544 PRO/1000 T Desktop Adapter A62947-xxx + 82540 PRO/1000 MT Desktop Adapter A78408-xxx + 82545 PRO/1000 MT Server Adapter A92165-xxx + 82546 PRO/1000 MT Dual Port Server Adapter A92111-xxx + 82545 PRO/1000 MF Server Adapter A91622-xxx + 82545 PRO/1000 MF Server Adapter(LX) A91624-xxx + 82546 PRO/1000 MF Dual Port Server Adapter A91620-xxx For more information on how to identify your adapter, go to the Adapter & Driver ID Guide at: @@ -1357,6 +1362,80 @@ The module will be called eepro100.o. If you want to compile it as a module, say M here and read as well as . + +CONFIG_E100 + This driver supports Intel(R) PRO/100 family of adapters, which + includes: + + Controller Adapter Name Board IDs + ---------- ------------ --------- + + 82558 PRO/100+ PCI Adapter 668081-xxx, + 689661-xxx + 82558 PRO/100+ Management Adapter 691334-xxx, + 701738-xxx, + 721383-xxx + 82558 PRO/100+ Dual Port Server Adapter 714303-xxx, + 711269-xxx, + A28276-xxx + 82558 PRO/100+ PCI Server Adapter 710550-xxx + 82550 PRO/100 S Server Adapter 752438-xxx + 82559 A56831-xxx, + A10563-xxx, + A12171-xxx, + A12321-xxx, + A12320-xxx, + A12170-xxx + 748568-xxx + 748565-xxx + 82550 PRO/100 S Desktop Adapter 751767-xxx + 82559 748592-xxx, + A12167-xxx, + A12318-xxx, + A12317-xxx, + A12165-xxx, + 748569-xxx + 82559 PRO/100+ Server Adapter 729757-xxx + 82559 PRO/100 S Management Adapter 748566-xxx, + 748564-xxx + 82550 PRO/100 S Dual Port Server Adapter A56831-xxx + 82551 PRO/100 M Desktop Adapter A80897-xxx + PRO/100 S Advanced Management Adapter + 747842-xxx, + 745171-xxx + CNR PRO/100 VE Desktop Adapter A10386-xxx, + A10725-xxx, + A23801-xxx, + A19716-xxx + PRO/100 VM Desktop Adapter A14323-xxx, + A19725-xxx, + A23801-xxx, + A22220-xxx, + A23796-xxx + + + To verify that your adapter is supported, find the board ID number + on the adapter. Look for a label that has a barcode and a number + in the format 123456-001 (six digits hyphen three digits). Match + this to the list of numbers above. + + For more information on how to identify your adapter, go to the + Adapter & Driver ID Guide at: + + http://support.intel.com/support/network/adapter/pro100/21397.htm + + For the latest Intel PRO/100 network driver for Linux, see: + + http://appsr.intel.com/scripts-df/support_intel.asp + + More specific information on configuring the driver is in + . + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called e100.o. If you want to compile it as a + module, say M here and read as well + as . CONFIG_FEALNX Say Y here to support the Mysom MTD-800 family of PCI-based Ethernet diff -Nru a/drivers/net/dl2k.c b/drivers/net/dl2k.c --- a/drivers/net/dl2k.c Sun Jun 2 18:44:57 2002 +++ b/drivers/net/dl2k.c Sun Jun 2 18:44:57 2002 @@ -29,24 +29,28 @@ 1.08 2002/01/17 Fixed the multicast bug. 1.09 2002/03/07 Move rx-poll-now to re-fill loop. Added rio_timer() to watch rx buffers. + 1.10 2002/04/16 Fixed miscount of carrier error. + 1.11 2002/05/23 Added ISR schedule scheme. + Fixed miscount of rx frame error for DGE-550SX. + Fixed VLAN bug. */ #include "dl2k.h" static char version[] __devinitdata = - KERN_INFO "D-Link DL2000-based linux driver v1.09 2002/03/07\n"; + KERN_INFO "D-Link DL2000-based linux driver v1.11 2002/05/23\n"; #define MAX_UNITS 8 static int mtu[MAX_UNITS]; static int vlan[MAX_UNITS]; static int jumbo[MAX_UNITS]; static char *media[MAX_UNITS]; -static int tx_flow[MAX_UNITS]; -static int rx_flow[MAX_UNITS]; +static int tx_flow=-1; +static int rx_flow=-1; static int copy_thresh; -static int rx_coalesce; /* Rx frame count each interrupt */ -static int rx_timeout; /* Rx DMA wait time in 64ns increments */ -static int tx_coalesce = DEFAULT_TXC; /* HW xmit count each TxComplete [1-8] */ +static int rx_coalesce=10; /* Rx frame count each interrupt */ +static int rx_timeout=200; /* Rx DMA wait time in 640ns increments */ +static int tx_coalesce=16; /* HW xmit count each TxDMAComplete */ MODULE_AUTHOR ("Edward Peng"); @@ -56,16 +60,16 @@ MODULE_PARM (media, "1-" __MODULE_STRING (MAX_UNITS) "s"); MODULE_PARM (vlan, "1-" __MODULE_STRING (MAX_UNITS) "i"); MODULE_PARM (jumbo, "1-" __MODULE_STRING (MAX_UNITS) "i"); -MODULE_PARM (tx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i"); -MODULE_PARM (rx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i"); +MODULE_PARM (tx_flow, "i"); +MODULE_PARM (rx_flow, "i"); MODULE_PARM (copy_thresh, "i"); MODULE_PARM (rx_coalesce, "i"); /* Rx frame count each interrupt */ MODULE_PARM (rx_timeout, "i"); /* Rx DMA wait time in 64ns increments */ -MODULE_PARM (tx_coalesce, "i"); /* HW xmit count each TxComplete [1-8] */ +MODULE_PARM (tx_coalesce, "i"); /* HW xmit count each TxDMAComplete */ /* Enable the default interrupts */ -#define DEFAULT_INTR (RxDMAComplete | HostError | IntRequested | TxComplete| \ +#define DEFAULT_INTR (RxDMAComplete | HostError | IntRequested | TxDMAComplete| \ UpdateStats | LinkEvent) #define EnableInt() \ writew(DEFAULT_INTR, ioaddr + IntEnable) @@ -75,16 +79,18 @@ static int rio_open (struct net_device *dev); static void rio_timer (unsigned long data); -static void tx_timeout (struct net_device *dev); +static void rio_tx_timeout (struct net_device *dev); static void alloc_list (struct net_device *dev); static int start_xmit (struct sk_buff *skb, struct net_device *dev); static void rio_interrupt (int irq, void *dev_instance, struct pt_regs *regs); +static void rio_free_tx (struct net_device *dev, int irq); static void tx_error (struct net_device *dev, int tx_status); static int receive_packet (struct net_device *dev); static void rio_error (struct net_device *dev, int int_status); static int change_mtu (struct net_device *dev, int new_mtu); static void set_multicast (struct net_device *dev); static struct net_device_stats *get_stats (struct net_device *dev); +static int clear_stats (struct net_device *dev); static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static int rio_close (struct net_device *dev); static int find_miiphy (struct net_device *dev); @@ -98,9 +104,6 @@ static int mii_read (struct net_device *dev, int phy_addr, int reg_num); static int mii_write (struct net_device *dev, int phy_addr, int reg_num, u16 data); -#ifdef RIO_DEBUG -static int rio_ioctl_ext (struct net_device *dev, struct ioctl_data *iodata); -#endif static int __devinit rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) @@ -109,7 +112,7 @@ struct netdev_private *np; static int card_idx; int chip_idx = ent->driver_data; - int err, irq = pdev->irq; + int err, irq; long ioaddr; static int version_printed; void *ring_space; @@ -122,6 +125,7 @@ if (err) return err; + irq = pdev->irq; err = pci_request_regions (pdev, "dl2k"); if (err) goto err_out_disable; @@ -149,7 +153,7 @@ np = dev->priv; np->chip_id = chip_idx; np->pdev = pdev; - spin_lock_init (&np->lock); + spin_lock_init (&np->tx_lock); spin_lock_init (&np->rx_lock); /* Parse manual configuration */ @@ -199,17 +203,18 @@ } np->vlan = (vlan[card_idx] > 0 && vlan[card_idx] < 4096) ? vlan[card_idx] : 0; - if (rx_coalesce != 0 && rx_timeout != 0) { + if (rx_coalesce > 0 && rx_timeout > 0) { np->rx_coalesce = rx_coalesce; np->rx_timeout = rx_timeout; np->coalesce = 1; } - np->tx_flow = (tx_flow[card_idx]) ? 1 : 0; - np->rx_flow = (rx_flow[card_idx]) ? 1 : 0; + np->tx_flow = (tx_flow == 0) ? 0 : 1; + np->rx_flow = (rx_flow == 0) ? 0 : 1; + if (tx_coalesce < 1) tx_coalesce = 1; - if (tx_coalesce > 8) - tx_coalesce = 8; + if (tx_coalesce > TX_RING_SIZE-1) + tx_coalesce = TX_RING_SIZE - 1; } dev->open = &rio_open; dev->hard_start_xmit = &start_xmit; @@ -217,7 +222,7 @@ dev->get_stats = &get_stats; dev->set_multicast_list = &set_multicast; dev->do_ioctl = &rio_ioctl; - dev->tx_timeout = &tx_timeout; + dev->tx_timeout = &rio_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; dev->change_mtu = &change_mtu; #if 0 @@ -247,6 +252,7 @@ /* Fiber device? */ np->phy_media = (readw(ioaddr + ASICCtrl) & PhyMedia) ? 1 : 0; + np->link_status = 0; /* Set media and reset PHY */ if (np->phy_media) { /* default 1000mbps_fd for fiber deivices */ @@ -281,6 +287,15 @@ dev->name, np->name, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], irq); + if (tx_coalesce > 1) + printk(KERN_INFO "tx_coalesce:\t%d packets\n", + tx_coalesce); + if (np->coalesce) + printk(KERN_INFO "rx_coalesce:\t%d packets\n" + KERN_INFO "rx_timeout: \t%d ns\n", + np->rx_coalesce, np->rx_timeout*640); + if (np->vlan) + printk(KERN_INFO "vlan(id):\t%d\n", np->vlan); return 0; err_out_unmap_rx: @@ -327,7 +342,7 @@ return 0; } -static int __devinit +int parse_eeprom (struct net_device *dev) { int i, j; @@ -346,7 +361,7 @@ } /* Check CRC */ - crc = ~ether_crc_le(256 - 4, sromdata); + crc = ~ether_crc_le(256 - 4, sromdata); if (psrom->crc != crc) { printk (KERN_ERR "%s: EEPROM data CRC error.\n", dev->name); return -1; @@ -431,8 +446,10 @@ writeb (0xff, ioaddr + TxDMAPollPeriod); writeb (0x30, ioaddr + RxDMABurstThresh); writeb (0x30, ioaddr + RxDMAUrgentThresh); - netif_start_queue (dev); - writel (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl); + + /* clear statistics */ + clear_stats (dev); + /* VLAN supported */ if (np->vlan) { /* priority field in RxDMAIntCtrl */ @@ -451,15 +468,20 @@ /* Enable default interrupts */ EnableInt (); - /* clear statistics */ - get_stats (dev); init_timer (&np->timer); np->timer.expires = jiffies + 1*HZ; np->timer.data = (unsigned long) dev; np->timer.function = &rio_timer; add_timer (&np->timer); + + /* Start Tx/Rx */ + writel (readl (ioaddr + MACCtrl) | StatsEnable | RxEnable | TxEnable, + ioaddr + MACCtrl); + + netif_start_queue (dev); return 0; } + static void rio_timer (unsigned long data) { @@ -469,10 +491,10 @@ int next_tick = 1*HZ; unsigned long flags; + spin_lock_irqsave(&np->rx_lock, flags); /* Recover rx ring exhausted error */ if (np->cur_rx - np->old_rx >= RX_RING_SIZE) { printk(KERN_INFO "Try to recover rx ring exhausted...\n"); - spin_lock_irqsave(&np->rx_lock, flags); /* Re-allocate skbuffs to fill the descriptor ring */ for (; np->cur_rx - np->old_rx > 0; np->old_rx++) { struct sk_buff *skb; @@ -500,43 +522,22 @@ cpu_to_le64 (np->rx_buf_sz) << 48; np->rx_ring[entry].status = 0; } /* end for */ - spin_unlock_irqrestore (&np->rx_lock, flags); } /* end if */ + spin_unlock_irqrestore (&np->rx_lock, flags); np->timer.expires = jiffies + next_tick; add_timer(&np->timer); } static void -tx_timeout (struct net_device *dev) +rio_tx_timeout (struct net_device *dev) { - struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; printk (KERN_INFO "%s: Tx timed out (%4.4x), is buffer full?\n", dev->name, readl (ioaddr + TxStatus)); - /* Free used tx skbuffs */ - for (; np->cur_tx - np->old_tx > 0; np->old_tx++) { - int entry = np->old_tx % TX_RING_SIZE; - struct sk_buff *skb; - - if (!(np->tx_ring[entry].status & TFDDone)) - break; - skb = np->tx_skbuff[entry]; - pci_unmap_single (np->pdev, - np->tx_ring[entry].fraginfo, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq (skb); - np->tx_skbuff[entry] = 0; - } + rio_free_tx(dev, 0); dev->if_port = 0; dev->trans_start = jiffies; - np->stats.tx_errors++; - /* If the ring is no longer full, clear tx_full and - call netif_wake_queue() */ - if (np->tx_full && np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1) { - np->tx_full = 0; - netif_wake_queue (dev); - } } /* allocate and initialize Tx and Rx descriptors */ @@ -546,7 +547,6 @@ struct netdev_private *np = dev->priv; int i; - np->tx_full = 0; np->cur_rx = np->cur_tx = 0; np->old_rx = np->old_tx = 0; np->rx_buf_sz = (dev->mtu <= 1500 ? PACKET_SIZE : dev->mtu + 32); @@ -605,18 +605,17 @@ struct netdev_desc *txdesc; unsigned entry; u32 ioaddr; - int tx_shift; - unsigned long flags; + u64 tfc_vlan_tag = 0; + if (np->link_status == 0) { /* Link Down */ + dev_kfree_skb(skb); + return 0; + } ioaddr = dev->base_addr; entry = np->cur_tx % TX_RING_SIZE; np->tx_skbuff[entry] = skb; txdesc = &np->tx_ring[entry]; - /* Set TFDDone to avoid TxDMA gather this descriptor */ - txdesc->status = cpu_to_le64 (TFDDone); - txdesc->status |= - cpu_to_le64 (entry | WordAlignDisable | (1 << FragCountShift)); #if 0 if (skb->ip_summed == CHECKSUM_HW) { txdesc->status |= @@ -630,31 +629,33 @@ (cpu_to_le64 (np->vlan) << 32) | (cpu_to_le64 (skb->priority) << 45); } - - /* Send one packet each time at 10Mbps mode */ - /* Tx coalescing loop do not exceed 8 */ - if (entry % tx_coalesce == 0 || np->speed == 10) - txdesc->status |= cpu_to_le64 (TxIndicate); txdesc->fraginfo = cpu_to_le64 (pci_map_single (np->pdev, skb->data, skb->len, PCI_DMA_TODEVICE)); txdesc->fraginfo |= cpu_to_le64 (skb->len) << 48; - /* Clear TFDDone, then TxDMA start to send this descriptor */ - txdesc->status &= ~cpu_to_le64 (TFDDone); - - DEBUG_TFD_DUMP (np); + /* DL2K bug: DMA fails to get next descriptor ptr in 10Mbps mode + * Work around: Always use 1 descriptor in 10Mbps mode */ + if (entry % tx_coalesce == 0 || np->speed == 10) + txdesc->status = cpu_to_le64 (entry | tfc_vlan_tag | + WordAlignDisable | + TxDMAIndicate | + (1 << FragCountShift)); + else + txdesc->status = cpu_to_le64 (entry | tfc_vlan_tag | + WordAlignDisable | + (1 << FragCountShift)); /* TxDMAPollNow */ writel (readl (ioaddr + DMACtrl) | 0x00001000, ioaddr + DMACtrl); - np->cur_tx++; - if (np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1 && np->speed != 10) { + /* Schedule ISR */ + writel(10000, ioaddr + CountDown); + np->cur_tx = (np->cur_tx + 1) % TX_RING_SIZE; + if ((np->cur_tx - np->old_tx + TX_RING_SIZE) % TX_RING_SIZE + < TX_QUEUE_LEN - 1 && np->speed != 10) { /* do nothing */ - } else { - spin_lock_irqsave(&np->lock, flags); - np->tx_full = 1; + } else if (!netif_queue_stopped(dev)) { netif_stop_queue (dev); - spin_unlock_irqrestore (&np->lock, flags); } /* The first TFDListPtr */ @@ -664,14 +665,6 @@ writel (0, dev->base_addr + TFDListPtr1); } - if (np->old_tx > TX_RING_SIZE) { - spin_lock_irqsave (&np->lock, flags); - tx_shift = TX_RING_SIZE; - np->old_tx -= tx_shift; - np->cur_tx -= tx_shift; - spin_unlock_irqrestore (&np->lock, flags); - } - /* NETDEV WATCHDOG timer */ dev->trans_start = jiffies; return 0; @@ -688,61 +681,79 @@ ioaddr = dev->base_addr; np = dev->priv; - spin_lock(&np->lock); while (1) { int_status = readw (ioaddr + IntStatus); writew (int_status, ioaddr + IntStatus); int_status &= DEFAULT_INTR; - if (int_status == 0) + if (int_status == 0 || --cnt < 0) break; /* Processing received packets */ if (int_status & RxDMAComplete) receive_packet (dev); - /* TxComplete interrupt */ - if ((int_status & TxComplete) || np->tx_full) { + /* TxDMAComplete interrupt */ + if ((int_status & (TxDMAComplete|IntRequested))) { int tx_status; tx_status = readl (ioaddr + TxStatus); if (tx_status & 0x01) tx_error (dev, tx_status); /* Free used tx skbuffs */ - for (;np->cur_tx - np->old_tx > 0; np->old_tx++) { - int entry = np->old_tx % TX_RING_SIZE; - struct sk_buff *skb; - - if (!(np->tx_ring[entry].status & TFDDone)) - break; - skb = np->tx_skbuff[entry]; - pci_unmap_single (np->pdev, - np->tx_ring[entry].fraginfo, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq (skb); - np->tx_skbuff[entry] = 0; - } - } - /* If the ring is no longer full, clear tx_full and - call netif_wake_queue() */ - if (np->tx_full && np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1) { - if (np->speed != 10 || int_status & TxComplete) { - np->tx_full = 0; - netif_wake_queue (dev); - } + rio_free_tx (dev, 1); } /* Handle uncommon events */ if (int_status & - (IntRequested | HostError | LinkEvent | UpdateStats)) + (HostError | LinkEvent | UpdateStats)) rio_error (dev, int_status); - /* If too much interrupts here, disable all interrupts except - IntRequest. When CountDown down to 0, IntRequest will - be caught by rio_error() to recovery the interrupts */ - if (--cnt < 0) { - get_stats (dev); - writel (1, ioaddr + CountDown); - writew (IntRequested, ioaddr + IntEnable); + } + if (np->cur_tx != np->old_tx) + writel (100, ioaddr + CountDown); +} + +static void +rio_free_tx (struct net_device *dev, int irq) +{ + struct netdev_private *np = (struct netdev_private *) dev->priv; + int entry = np->old_tx % TX_RING_SIZE; + int tx_use = 0; + long flag = 0; + + if (irq) + spin_lock_irqsave(&np->tx_lock, flag); + else + spin_lock(&np->tx_lock); + /* Free used tx skbuffs */ + while (entry != np->cur_tx) { + struct sk_buff *skb; + + if (!(np->tx_ring[entry].status & TFDDone)) break; - } + skb = np->tx_skbuff[entry]; + pci_unmap_single (np->pdev, + np->tx_ring[entry].fraginfo, + skb->len, PCI_DMA_TODEVICE); + if (irq) + dev_kfree_skb_irq (skb); + else + dev_kfree_skb (skb); + + np->tx_skbuff[entry] = 0; + entry = (entry + 1) % TX_RING_SIZE; + tx_use++; + } + if (irq) + spin_unlock_irqrestore(&np->tx_lock, flag); + else + spin_unlock(&np->tx_lock); + np->old_tx = entry; + + /* If the ring is no longer full, clear tx_full and + call netif_wake_queue() */ + + if (netif_queue_stopped(dev) && + ((np->cur_tx - np->old_tx + TX_RING_SIZE) % TX_RING_SIZE + < TX_QUEUE_LEN - 1 || np->speed == 10)) { + netif_wake_queue (dev); } - spin_unlock(&np->lock); } static void @@ -755,11 +766,10 @@ np = dev->priv; - frame_id = (tx_status & 0xffff0000) >> 16; + frame_id = (tx_status & 0xffff0000); printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n", dev->name, tx_status, frame_id); np->stats.tx_errors++; - np->stats.tx_dropped++; /* Ttransmit Underrun */ if (tx_status & 0x10) { np->stats.tx_fifo_errors++; @@ -774,20 +784,7 @@ break; mdelay (1); } - /* Free completed descriptors */ - for (; np->cur_tx - np->old_tx > 0; np->old_tx++) { - int entry = np->old_tx % TX_RING_SIZE; - struct sk_buff *skb; - if (!(np->tx_ring[entry].status & TFDDone)) - break; - - skb = np->tx_skbuff[entry]; - pci_unmap_single (np->pdev, np->tx_ring[entry].fraginfo, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq (skb); - np->tx_skbuff[entry] = 0; - } - + rio_free_tx (dev, 1); /* Reset TFDListPtr */ writel (np->tx_ring_dma + np->old_tx * sizeof (struct netdev_desc), @@ -810,14 +807,13 @@ /* Let TxStartThresh stay default value */ } /* Maximum Collisions */ -#ifdef ETHER_STATS - if (tx_status & 0x08) +#ifdef ETHER_STATS + if (tx_status & 0x08) np->stats.collisions16++; #else - if (tx_status & 0x08) + if (tx_status & 0x08) np->stats.collisions++; #endif - /* Restart the Tx */ writel (readw (dev->base_addr + MACCtrl) | TxEnable, ioaddr + MACCtrl); } @@ -827,16 +823,8 @@ { struct netdev_private *np = (struct netdev_private *) dev->priv; int entry = np->cur_rx % RX_RING_SIZE; - int cnt = np->old_rx + RX_RING_SIZE - np->cur_rx; - int rx_shift; + int cnt = 30; - spin_lock (&np->rx_lock); - if (np->old_rx > RX_RING_SIZE) { - rx_shift = RX_RING_SIZE; - np->old_rx -= rx_shift; - np->cur_rx -= rx_shift; - } - DEBUG_RFD_DUMP (np, 1); /* If RFDDone, FrameStart and FrameEnd set, there is a new packet in. */ while (1) { struct netdev_desc *desc = &np->rx_ring[entry]; @@ -852,20 +840,19 @@ frame_status = le64_to_cpu (desc->status); if (--cnt < 0) break; - DEBUG_PKT_DUMP (np, pkt_len); pci_dma_sync_single (np->pdev, desc->fraginfo, np->rx_buf_sz, PCI_DMA_FROMDEVICE); /* Update rx error statistics, drop packet. */ - if (frame_status & 0x003f0000) { + if (frame_status & RFS_Errors) { np->stats.rx_errors++; - if (frame_status & 0x00300000) + if (frame_status & (RxRuntFrame | RxLengthError)) np->stats.rx_length_errors++; - if (frame_status & 0x00010000) - np->stats.rx_fifo_errors++; - if (frame_status & 0x00060000) - np->stats.rx_frame_errors++; - if (frame_status & 0x00080000) + if (frame_status & RxFCSError) np->stats.rx_crc_errors++; + if (frame_status & RxAlignmentError && np->speed != 1000) + np->stats.rx_frame_errors++; + if (frame_status & RxFIFOOverrun) + np->stats.rx_fifo_errors++; } else { struct sk_buff *skb; @@ -893,17 +880,17 @@ skb->ip_summed = CHECKSUM_UNNECESSARY; } #endif - netif_rx (skb); dev->last_rx = jiffies; } - entry = (++np->cur_rx) % RX_RING_SIZE; - + entry = (entry + 1) % RX_RING_SIZE; } + spin_lock(&np->rx_lock); + np->cur_rx = entry; /* Re-allocate skbuffs to fill the descriptor ring */ - for (; np->cur_rx - np->old_rx > 0; np->old_rx++) { + entry = np->old_rx; + while (entry != np->cur_rx) { struct sk_buff *skb; - entry = np->old_rx % RX_RING_SIZE; /* Dropped packets don't need to re-allocate */ if (np->rx_skbuff[entry] == NULL) { skb = dev_alloc_skb (np->rx_buf_sz); @@ -927,11 +914,9 @@ np->rx_ring[entry].fraginfo |= cpu_to_le64 (np->rx_buf_sz) << 48; np->rx_ring[entry].status = 0; - /* RxDMAPollNow */ - writel (readl (dev->base_addr + DMACtrl) | 0x00000010, - dev->base_addr + DMACtrl); + entry = (entry + 1) % RX_RING_SIZE; } - DEBUG_RFD_DUMP (np, 2); + np->old_rx = entry; spin_unlock(&np->rx_lock); return 0; } @@ -943,14 +928,6 @@ struct netdev_private *np = dev->priv; u16 macctrl; - /* Stop the down counter and recovery the interrupt */ - if (int_status & IntRequested) { - writew (0, ioaddr + IntEnable); - writel (0, ioaddr + CountDown); - /* Enable default interrupts */ - EnableInt (); - } - /* Link change event */ if (int_status & LinkEvent) { if (mii_wait_link (dev, 10) == 0) { @@ -960,14 +937,19 @@ else mii_get_media (dev); macctrl = 0; + macctrl |= (np->vlan) ? AutoVLANuntagging : 0; macctrl |= (np->full_duplex) ? DuplexSelect : 0; macctrl |= (np->tx_flow) ? TxFlowControlEnable : 0; macctrl |= (np->rx_flow) ? RxFlowControlEnable : 0; writew(macctrl, ioaddr + MACCtrl); + np->link_status = 1; + netif_carrier_on(dev); } else { printk (KERN_INFO "%s: Link off\n", dev->name); + np->link_status = 0; + netif_carrier_off(dev); } } @@ -991,41 +973,100 @@ { long ioaddr = dev->base_addr; struct netdev_private *np = dev->priv; - u16 temp1; - u16 temp2; int i; + unsigned int stat_reg; + /* All statistics registers need to be acknowledged, else statistic overflow could cause problems */ + np->stats.rx_packets += readl (ioaddr + FramesRcvOk); np->stats.tx_packets += readl (ioaddr + FramesXmtOk); np->stats.rx_bytes += readl (ioaddr + OctetRcvOk); np->stats.tx_bytes += readl (ioaddr + OctetXmtOk); - temp1 = readw (ioaddr + FrameLostRxError); - np->stats.rx_errors += temp1; - np->stats.rx_missed_errors += temp1; - np->stats.tx_dropped += readw (ioaddr + FramesAbortXSColls); - temp1 = readl (ioaddr + SingleColFrames) + - readl (ioaddr + MultiColFrames) + readl (ioaddr + LateCollisions); - temp2 = readw (ioaddr + CarrierSenseErrors); - np->stats.tx_carrier_errors += temp2; - np->stats.tx_errors += readw (ioaddr + FramesWEXDeferal) + - readl (ioaddr + FramesWDeferredXmt) + temp2; - - /* detailed rx_error */ - np->stats.rx_length_errors += readw (ioaddr + FrameTooLongErrors); - np->stats.rx_crc_errors += readw (ioaddr + FrameCheckSeqError); + + np->stats.multicast = readl (ioaddr + McstFramesRcvdOk); + np->stats.collisions += readl (ioaddr + SingleColFrames) + + readl (ioaddr + MultiColFrames); + + /* detailed tx errors */ + stat_reg = readw (ioaddr + FramesAbortXSColls); + np->stats.tx_aborted_errors += stat_reg; + np->stats.tx_errors += stat_reg; + + stat_reg = readw (ioaddr + CarrierSenseErrors); + np->stats.tx_carrier_errors += stat_reg; + np->stats.tx_errors += stat_reg; /* Clear all other statistic register. */ - readw (ioaddr + InRangeLengthErrors); - readw (ioaddr + MacControlFramesXmtd); + readl (ioaddr + McstOctetXmtOk); readw (ioaddr + BcstFramesXmtdOk); readl (ioaddr + McstFramesXmtdOk); + readw (ioaddr + BcstFramesRcvdOk); + readw (ioaddr + MacControlFramesRcvd); + readw (ioaddr + FrameTooLongErrors); + readw (ioaddr + InRangeLengthErrors); + readw (ioaddr + FramesCheckSeqErrors); + readw (ioaddr + FramesLostRxErrors); + readl (ioaddr + McstOctetXmtOk); readl (ioaddr + BcstOctetXmtOk); + readl (ioaddr + McstFramesXmtdOk); + readl (ioaddr + FramesWDeferredXmt); + readl (ioaddr + LateCollisions); + readw (ioaddr + BcstFramesXmtdOk); + readw (ioaddr + MacControlFramesXmtd); + readw (ioaddr + FramesWEXDeferal); + + + for (i = 0x100; i <= 0x150; i += 4) + readl (ioaddr + i); + readw (ioaddr + TxJumboFrames); + readw (ioaddr + RxJumboFrames); + readw (ioaddr + TCPCheckSumErrors); + readw (ioaddr + UDPCheckSumErrors); + readw (ioaddr + IPCheckSumErrors); + return &np->stats; +} + +static int +clear_stats (struct net_device *dev) +{ + long ioaddr = dev->base_addr; + int i; + + /* All statistics registers need to be acknowledged, + else statistic overflow could cause problems */ + readl (ioaddr + FramesRcvOk); + readl (ioaddr + FramesXmtOk); + readl (ioaddr + OctetRcvOk); + readl (ioaddr + OctetXmtOk); + + readl (ioaddr + McstFramesRcvdOk); + readl (ioaddr + SingleColFrames); + readl (ioaddr + MultiColFrames); + readl (ioaddr + LateCollisions); + /* detailed rx errors */ + readw (ioaddr + FrameTooLongErrors); + readw (ioaddr + InRangeLengthErrors); + readw (ioaddr + FramesCheckSeqErrors); + readw (ioaddr + FramesLostRxErrors); + + /* detailed tx errors */ + readw (ioaddr + FramesAbortXSColls); + readw (ioaddr + CarrierSenseErrors); + + /* Clear all other statistic register. */ readl (ioaddr + McstOctetXmtOk); + readw (ioaddr + BcstFramesXmtdOk); + readl (ioaddr + McstFramesXmtdOk); + readw (ioaddr + BcstFramesRcvdOk); readw (ioaddr + MacControlFramesRcvd); - readw (ioaddr + BcstFramesRcvOk); - readl (ioaddr + McstFramesRcvOk); - readl (ioaddr + BcstOctetRcvOk); + readl (ioaddr + McstOctetXmtOk); + readl (ioaddr + BcstOctetXmtOk); + readl (ioaddr + McstFramesXmtdOk); + readl (ioaddr + FramesWDeferredXmt); + readw (ioaddr + BcstFramesXmtdOk); + readw (ioaddr + MacControlFramesXmtd); + readw (ioaddr + FramesWEXDeferal); for (i = 0x100; i <= 0x150; i += 4) readl (ioaddr + i); @@ -1034,9 +1075,10 @@ readw (ioaddr + TCPCheckSumErrors); readw (ioaddr + UDPCheckSumErrors); readw (ioaddr + IPCheckSumErrors); - return &np->stats; + return 0; } + int change_mtu (struct net_device *dev, int new_mtu) { @@ -1111,51 +1153,35 @@ int phy_addr; struct netdev_private *np = dev->priv; struct mii_data *miidata = (struct mii_data *) &rq->ifr_data; -#ifdef RIO_DEBUG - struct ioctl_data *iodata = (struct ioctl_data *) (rq->ifr_data); -#endif - u16 *data = (u16 *) & rq->ifr_data; + struct netdev_desc *desc; int i; phy_addr = np->phy_addr; switch (cmd) { case SIOCDEVPRIVATE: -#ifdef RIO_DEBUG - if (rio_ioctl_ext (dev, iodata) != 0) - return -EOPNOTSUPP; break; -#else - return -EOPNOTSUPP; -#endif + case SIOCDEVPRIVATE + 1: miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num); break; case SIOCDEVPRIVATE + 2: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; mii_write (dev, phy_addr, miidata->reg_num, miidata->in_value); break; case SIOCDEVPRIVATE + 3: - np->rx_debug = (data[0] <= 7) ? data[0] : 0; - printk ("rx_debug = %d\n", np->rx_debug); break; case SIOCDEVPRIVATE + 4: - np->tx_debug = (data[0] <= 7) ? data[0] : 0; - printk ("tx_debug = %d\n", np->tx_debug); break; case SIOCDEVPRIVATE + 5: - np->tx_full = 1; netif_stop_queue (dev); break; case SIOCDEVPRIVATE + 6: - np->tx_full = 0; netif_wake_queue (dev); break; case SIOCDEVPRIVATE + 7: printk ("tx_full=%x cur_tx=%lx old_tx=%lx cur_rx=%lx old_rx=%lx\n", - np->tx_full, np->cur_tx, np->old_tx, np->cur_rx, + netif_queue_stopped(dev), np->cur_tx, np->old_tx, np->cur_rx, np->old_rx); break; case SIOCDEVPRIVATE + 8: @@ -1163,7 +1189,8 @@ for (i = 0; i < TX_RING_SIZE; i++) { desc = &np->tx_ring[i]; printk - ("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x", + ("%02x:cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x", + i, (u32) (np->tx_ring_dma + i * sizeof (*desc)), (u32) desc->next_desc, (u32) desc->status, (u32) (desc->fraginfo >> 32), @@ -1172,110 +1199,17 @@ } printk ("\n"); break; - default: - return -EOPNOTSUPP; - } - return 0; -} - -#ifdef RIO_DEBUG -int -rio_ioctl_ext (struct net_device *dev, struct ioctl_data *iodata) -{ - struct netdev_private *np = dev->priv; - int phy_addr = np->phy_addr; - u32 hi, lo; - int i; - BMCR_t bmcr; - BMSR_t bmsr; - - if (iodata == NULL) - goto invalid_cmd; - if (strcmp (iodata->signature, "rio") != 0) - goto invalid_cmd; - - switch (iodata->cmd) { - case 0: - for (i = 0; i < TX_RING_SIZE; i++) { - hi = np->tx_ring[i].status >> 32; - lo = np->tx_ring[i].status; - printk ("TFC=%08x %08x \n", hi, lo); - - } - break; - case 1: - for (i = 0; i < RX_RING_SIZE; i++) { - hi = np->rx_ring[i].status >> 32; - lo = np->rx_ring[i].status; - printk ("RFS=%08x %08x \n", hi, lo); - } - break; - case 2: - break; - case 3: - if (iodata->data != NULL) - np->tx_debug = iodata->data[0]; - break; - case 4: - /* Soft reset PHY */ - mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET); - bmcr.image = 0; - bmcr.bits.an_enable = 1; - bmcr.bits.reset = 1; - mii_write (dev, phy_addr, MII_BMCR, bmcr.image); - break; - case 5: - mii_write (dev, phy_addr, MII_BMCR, 0x1940); - mdelay (10); - mii_write (dev, phy_addr, MII_BMCR, 0x1940); - mdelay (100); /* wait a certain time */ - break; - case 6: - /* 5) Set media and Power Up */ - bmcr.image = 0; - bmcr.bits.power_down = 1; - if (np->an_enable) { - bmcr.bits.an_enable = 1; - } else { - if (np->speed == 100) { - bmcr.bits.speed100 = 1; - bmcr.bits.speed1000 = 0; - printk ("Manual 100 Mbps, "); - } else if (np->speed == 10) { - bmcr.bits.speed100 = 0; - bmcr.bits.speed1000 = 0; - printk ("Manual 10 Mbps, "); - } - if (np->full_duplex) { - bmcr.bits.duplex_mode = 1; - printk ("Full duplex. \n"); - } else { - bmcr.bits.duplex_mode = 0; - printk ("Half duplex.\n"); - } - } - mii_write (dev, phy_addr, MII_BMCR, bmcr.image); - break; - case 7: - bmcr.image = mii_read (dev, phy_addr, MII_BMCR); - bmsr.image = mii_read (dev, phy_addr, MII_BMSR); - printk ("BMCR=%x BMSR=%x LinkUp=%d\n", - bmcr.image, bmsr.image, bmsr.bits.link_status); - break; default: return -EOPNOTSUPP; } return 0; - - invalid_cmd: - return -1; } -#endif + #define EEP_READ 0x0200 #define EEP_BUSY 0x8000 /* Read the EEPROM word */ -static int __devinit +int read_eeprom (long ioaddr, int eep_addr) { int i = 1000; @@ -1441,10 +1375,11 @@ printk (KERN_INFO "Auto 10 Mbps, Half duplex\n"); } if (negotiate.bits.pause) { - np->tx_flow = 1; - np->rx_flow = 1; + np->tx_flow &= 1; + np->rx_flow &= 1; } else if (negotiate.bits.asymmetric) { - np->rx_flow = 1; + np->tx_flow = 0; + np->rx_flow &= 1; } /* else tx_flow, rx_flow = user select */ } else { @@ -1593,10 +1528,11 @@ np->full_duplex = 0; } if (negotiate.bits.pause) { - np->tx_flow = 1; - np->rx_flow = 1; + np->tx_flow &= 1; + np->rx_flow &= 1; } else if (negotiate.bits.asymmetric) { - np->rx_flow = 1; + np->tx_flow = 0; + np->rx_flow &= 1; } /* else tx_flow, rx_flow = user select */ } else { diff -Nru a/drivers/net/dl2k.h b/drivers/net/dl2k.h --- a/drivers/net/dl2k.h Sun Jun 2 18:44:57 2002 +++ b/drivers/net/dl2k.h Sun Jun 2 18:44:57 2002 @@ -119,13 +119,13 @@ McstOctetRcvOk = 0xac, BcstOctetRcvOk = 0xb0, FramesRcvOk = 0xb4, - McstFramesRcvOk = 0xb8, - BcstFramesRcvOk = 0xbe, + McstFramesRcvdOk = 0xb8, + BcstFramesRcvdOk = 0xbe, MacControlFramesRcvd = 0xc6, FrameTooLongErrors = 0xc8, InRangeLengthErrors = 0xca, - FrameCheckSeqError = 0xcc, - FrameLostRxError = 0xce, + FramesCheckSeqErrors = 0xcc, + FramesLostRxErrors = 0xce, OctetXmtOk = 0xd0, McstOctetXmtOk = 0xd4, BcstOctetXmtOk = 0xd8, @@ -264,6 +264,7 @@ FrameEnd = 0x40000000, RFDDone = 0x80000000, TCIShift = 32, + RFS_Errors = 0x003f0000, }; #define MII_RESET_TIME_OUT 10000 @@ -648,7 +649,7 @@ dma_addr_t tx_ring_dma; dma_addr_t rx_ring_dma; struct pci_dev *pdev; - spinlock_t lock; + spinlock_t tx_lock; spinlock_t rx_lock; struct net_device_stats stats; unsigned int rx_buf_sz; /* Based on MTU+slack. */ @@ -657,7 +658,6 @@ unsigned int chip_id; /* PCI table chip id */ unsigned int rx_coalesce; /* Maximum frames each RxDMAComplete intr */ unsigned int rx_timeout; /* Wait time between RxDMAComplete intr */ - unsigned int tx_full:1; /* The Tx queue is full. */ unsigned int full_duplex:1; /* Full-duplex operation requested. */ unsigned int an_enable:2; /* Auto-Negotiated Enable */ unsigned int jumbo:1; /* Jumbo frame enable */ @@ -665,6 +665,7 @@ unsigned int tx_flow:1; /* Tx flow control enable */ unsigned int rx_flow:1; /* Rx flow control enable */ unsigned int phy_media:1; /* 1: fiber, 0: copper */ + unsigned int link_status:1; /* Current link status */ unsigned char pci_rev_id; /* PCI revision ID */ struct netdev_desc *last_tx; /* Last Tx descriptor used. */ unsigned long cur_rx, old_rx; /* Producer/consumer ring indices */ @@ -677,8 +678,6 @@ u16 advertising; /* NWay media advertisement */ u16 negotiate; /* Negotiated media */ int phy_addr; /* PHY addresses. */ - int tx_debug; - int rx_debug; }; /* The station address location in the EEPROM. */ @@ -707,114 +706,4 @@ #define DEFAULT_RXT 750 #define DEFAULT_TXC 1 #define MAX_TXC 8 -#ifdef RIO_DEBUG -#define DEBUG_TFD_DUMP(x) debug_tfd_dump(x) -#define DEBUG_RFD_DUMP(x,flag) debug_rfd_dump(x,flag) -#define DEBUG_PKT_DUMP(x,len) debug_pkt_dump(x,len) -#define DEBUG_PRINT printk - -static inline void -debug_tfd_dump (struct netdev_private *np) -{ - int i; - struct netdev_desc *desc; - - if (np->tx_debug == 6) { - printk ("TFDone Dump: "); - for (i = 0; i < TX_RING_SIZE; i++) { - desc = &np->tx_ring[i]; - if ((desc->fraginfo & 0xffffffffff) == 0) - printk ("X"); - else - printk ("%d", (desc->status & TFDDone) ? 1 : 0); - } - printk ("\n"); - } - if (np->tx_debug == 5) { - for (i = 0; i < TX_RING_SIZE; i++) { - desc = &np->tx_ring[i]; - printk - ("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x", - (u32) np->tx_ring_dma + i * sizeof (*desc), - (u32) desc->next_desc, (u32) desc->status, - (u32) (desc->fraginfo >> 32), - (u32) desc->fraginfo); - printk ("\n"); - } - printk ("\n"); - } -} -static inline void -debug_rfd_dump (struct netdev_private *np, int flag) -{ - int i; - struct netdev_desc *desc; - int entry = np->cur_rx % RX_RING_SIZE; - - if (np->rx_debug == 5) { - for (i = 0; i < RX_RING_SIZE; i++) { - desc = &np->rx_ring[i]; - printk - ("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x", - (u32) np->rx_ring_dma + i * sizeof (*desc), - (u32) desc->next_desc, (u32) desc->status, - (u32) (desc->fraginfo >> 32), - (u32) desc->fraginfo); - printk ("\n"); - } - printk ("\n"); - } - - if (np->rx_debug == 6) { - if (flag == 1) - printk ("RFDone Dump: "); - else if (flag == 2) - printk ("Re-Filling: "); - for (i = 0; i < RX_RING_SIZE; i++) { - desc = &np->rx_ring[i]; - printk ("%d", (desc->status & RFDDone) ? 1 : 0); - } - printk ("\n"); - } - if (np->rx_debug == 7) { - printk (" In rcv_pkt(), entry %d status %4.4x %4.4x.\n", - entry, (u32) (np->rx_ring[entry].status >> 32), - (u32) np->rx_ring[entry].status); - } - -} - -static inline void -debug_pkt_dump (struct netdev_private *np, int pkt_len) -{ - int entry = np->cur_rx % RX_RING_SIZE; - struct netdev_desc *desc = &np->rx_ring[entry]; - u64 frame_status = le64_to_cpu (desc->status); - unsigned char *pchar; - unsigned char *phead; - int i; - - if (np->rx_debug == 4) { - printk (" rcv_pkt: status was %4.4x %4.4x.\n", - (u32) (frame_status >> 32), (u32) frame_status); - } - if (np->rx_debug == 7) { - -#error Please convert me to Documentation/DMA-mapping.txt - phead = - bus_to_virt (le64_to_cpu (desc->fraginfo & 0xffffffffff)); - for (pchar = phead, i = 0; i < pkt_len; i++, pchar++) { - printk ("%02x ", *pchar); - if ((i + 1) % 20 == 0) - printk ("\n"); - } - } -} -#else -#define DEBUG_TFD_DUMP(x) {} -#define DEBUG_RFD_DUMP(x,flag) {} -#define DEBUG_PKT_DUMP(x,len) {} -#define DEBUG_PRINT() {} -#endif - #endif /* __DL2K_H__ */ diff -Nru a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h --- a/drivers/net/e100/e100.h Sun Jun 2 18:44:57 2002 +++ b/drivers/net/e100/e100.h Sun Jun 2 18:44:57 2002 @@ -503,6 +503,7 @@ #define IS_BACHELOR 0x00000010 /* set if 82558 or newer board */ #define IS_ICH 0x00000020 #define DF_SPEED_FORCED 0x00000040 /* set if speed is forced */ +#define LED_IS_ON 0x00000080 /* LED is turned ON by the driver */ typedef struct net_device_stats net_dev_stats_t; @@ -909,7 +910,6 @@ }; #endif - struct e100_private { u32 flags; /* board management flags */ u32 tx_per_underrun; /* number of good tx frames per underrun */ @@ -998,8 +998,11 @@ u32 wolopts; u16 ip_lbytes; #endif -#ifdef ETHTOOL_TEST -struct ethtool_lpbk_data loopback; +#ifdef ETHTOOL_TEST + struct ethtool_lpbk_data loopback; +#endif +#ifdef ETHTOOL_PHYS_ID + struct timer_list blink_timer; /* led blink timer id */ #endif #ifdef CONFIG_PM diff -Nru a/drivers/net/e100/e100_config.c b/drivers/net/e100/e100_config.c --- a/drivers/net/e100/e100_config.c Sun Jun 2 18:44:57 2002 +++ b/drivers/net/e100/e100_config.c Sun Jun 2 18:44:57 2002 @@ -593,7 +593,6 @@ } #endif -#ifdef ETHTOOL_TEST /** * e100_config_loopback_mode * @bdp: atapter's private data struct @@ -690,5 +689,4 @@ return bc_changed; } -#endif diff -Nru a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c --- a/drivers/net/e100/e100_main.c Sun Jun 2 18:44:57 2002 +++ b/drivers/net/e100/e100_main.c Sun Jun 2 18:44:57 2002 @@ -164,6 +164,9 @@ }; #endif +#ifdef ETHTOOL_PHYS_ID +static int e100_ethtool_led_blink(struct net_device *, struct ifreq *); +#endif #endif /*E100_ETHTOOL_IOCTL */ #ifdef SIOCGMIIPHY @@ -182,7 +185,7 @@ /* Global Data structures and variables */ char e100_copyright[] __devinitdata = "Copyright (c) 2002 Intel Corporation"; -#define E100_VERSION "2.0.27-pre3" +#define E100_VERSION "2.0.30-k1" #define E100_FULL_DRIVER_NAME "Intel(R) PRO/100 Fast Ethernet Adapter - Loadable driver, ver " @@ -691,9 +694,10 @@ #ifdef ETHTOOL_GWOL /* Disabling all WOLs as initialization */ bdp->wolsupported = bdp->wolopts = 0; - if (bdp->rev_id >= D101MA_REV_ID) { - bdp->wolsupported = - WAKE_PHY | WAKE_UCAST | WAKE_ARP | WAKE_MAGIC; + if (bdp->rev_id >= D101A4_REV_ID) { + bdp->wolsupported = WAKE_PHY | WAKE_MAGIC; + if (bdp->rev_id >= D101MA_REV_ID) + bdp->wolsupported |= WAKE_UCAST | WAKE_ARP; bdp->wolopts = WAKE_MAGIC; } #endif @@ -3335,6 +3339,11 @@ rc = e100_ethtool_gstrings(dev,ifr); break; #endif +#ifdef ETHTOOL_PHYS_ID + case ETHTOOL_PHYS_ID: + rc = e100_ethtool_led_blink(dev,ifr); + break; +#endif default: break; } //switch @@ -3637,6 +3646,94 @@ if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) return -EFAULT; } + return 0; +} +#endif + +#ifdef ETHTOOL_PHYS_ID +#define E100_BLINK_INTERVAL (HZ/4) +/** + * e100_led_control + * @bdp: atapter's private data struct + * @led_mdi_op: led operation + * + * Software control over adapter's led. The possible operations are: + * TURN LED OFF, TURN LED ON and RETURN LED CONTROL TO HARDWARE. + */ +static void +e100_led_control(struct e100_private *bdp, u16 led_mdi_op) +{ + spin_lock_bh(&bdp->mdi_access_lock); + + e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL, + bdp->phy_addr, led_mdi_op); + + spin_unlock_bh(&bdp->mdi_access_lock); +} +/** + * e100_led_blink_callback + * @data: pointer to atapter's private data struct + * + * Blink timer callback function. Toggles ON/OFF led status bit and calls + * led hardware access function. + */ +static void +e100_led_blink_callback(unsigned long data) +{ + struct e100_private *bdp = (struct e100_private *) data; + + if(bdp->flags & LED_IS_ON) { + bdp->flags &= ~LED_IS_ON; + e100_led_control(bdp, PHY_82555_LED_OFF); + } else { + bdp->flags |= LED_IS_ON; + if (bdp->rev_id >= D101MA_REV_ID) + e100_led_control(bdp, PHY_82555_LED_ON_559); + else + e100_led_control(bdp, PHY_82555_LED_ON_PRE_559); + } + + mod_timer(&bdp->blink_timer, jiffies + E100_BLINK_INTERVAL); +} +/** + * e100_ethtool_led_blink + * @dev: pointer to atapter's net_device struct + * @ifr: pointer to ioctl request structure + * + * Blink led ioctl handler. Initialtes blink timer and sleeps until + * blink period expires. Than it kills timer and returns. The led control + * is returned back to hardware when blink timer is killed. + */ +static int +e100_ethtool_led_blink(struct net_device *dev, struct ifreq *ifr) +{ + struct e100_private *bdp; + struct ethtool_value ecmd; + + bdp = dev->priv; + + if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) + return -EFAULT; + + if(!bdp->blink_timer.function) { + init_timer(&bdp->blink_timer); + bdp->blink_timer.function = e100_led_blink_callback; + bdp->blink_timer.data = (unsigned long) bdp; + } + + mod_timer(&bdp->blink_timer, jiffies); + + set_current_state(TASK_INTERRUPTIBLE); + + if ((!ecmd.data) || (ecmd.data > MAX_SCHEDULE_TIMEOUT / HZ)) + ecmd.data = MAX_SCHEDULE_TIMEOUT / HZ; + + schedule_timeout(ecmd.data * HZ); + + del_timer_sync(&bdp->blink_timer); + + e100_led_control(bdp, PHY_82555_LED_NORMAL_CONTROL); + return 0; } #endif diff -Nru a/drivers/net/e100/e100_proc.c b/drivers/net/e100/e100_proc.c --- a/drivers/net/e100/e100_proc.c Sun Jun 2 18:44:57 2002 +++ b/drivers/net/e100/e100_proc.c Sun Jun 2 18:44:57 2002 @@ -548,7 +548,7 @@ int len; len = read_int_param(page, "CPU Saver Maximum Bundle", - "Sets the value for CPU saver's maximum value", + "Sets CPU saver's maximum value", E100_DEFAULT_CPUSAVER_BUNDLE_MAX, 0x1, 0xFFFF); return generic_read(page, start, off, count, eof, len); diff -Nru a/drivers/net/e100/e100_test.c b/drivers/net/e100/e100_test.c --- a/drivers/net/e100/e100_test.c Sun Jun 2 18:44:57 2002 +++ b/drivers/net/e100/e100_test.c Sun Jun 2 18:44:57 2002 @@ -69,6 +69,7 @@ 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. *******************************************************************************/ + #include "e100.h" #include "e100_config.h" #ifdef ETHTOOL_TEST @@ -457,11 +458,4 @@ } #endif - - - - - - - diff -Nru a/drivers/net/e1000/Makefile b/drivers/net/e1000/Makefile --- a/drivers/net/e1000/Makefile Sun Jun 2 18:44:56 2002 +++ b/drivers/net/e1000/Makefile Sun Jun 2 18:44:56 2002 @@ -1,3 +1,76 @@ +################################################################################ +# +# This software program is available to you under a choice of one of two +# licenses. You may choose to be licensed under either the GNU General Public +# License 2.0, June 1991, available at http://www.fsf.org/copyleft/gpl.html, +# or the Intel BSD + Patent License, the text of which follows: +# +# Recipient has requested a license and Intel Corporation ("Intel") is willing +# to grant a license for the software entitled Linux Base Driver for the +# Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided +# by Intel Corporation. The following definitions apply to this license: +# +# "Licensed Patents" means patent claims licensable by Intel Corporation which +# are necessarily infringed by the use of sale of the Software alone or when +# combined with the operating system referred to below. +# +# "Recipient" means the party to whom Intel delivers this Software. +# +# "Licensee" means Recipient and those third parties that receive a license to +# any operating system available under the GNU General Public License 2.0 or +# later. +# +# Copyright (c) 1999 - 2002 Intel Corporation. +# All rights reserved. +# +# The license is provided to Recipient and Recipient's Licensees under the +# following terms. +# +# Redistribution and use in source and binary forms of the Software, with or +# without modification, are permitted provided that the following conditions +# are met: +# +# Redistributions of source code of the Software may retain the above +# copyright notice, this list of conditions and the following disclaimer. +# +# Redistributions in binary form of the Software may reproduce the above +# copyright notice, this list of conditions and the following disclaimer in +# the documentation and/or materials provided with the distribution. +# +# Neither the name of Intel Corporation nor the names of its contributors +# shall be used to endorse or promote products derived from this Software +# without specific prior written permission. +# +# Intel hereby grants Recipient and Licensees a non-exclusive, worldwide, +# royalty-free patent license under Licensed Patents to make, use, sell, offer +# to sell, import and otherwise transfer the Software, if any, in source code +# and object code form. This license shall include changes to the Software +# that are error corrections or other minor changes to the Software that do +# not add functionality or features when the Software is incorporated in any +# version of an operating system that has been distributed under the GNU +# General Public License 2.0 or later. This patent license shall apply to the +# combination of the Software and any operating system licensed under the GNU +# General Public License 2.0 or later if, at the time Intel provides the +# Software to Recipient, such addition of the Software to the then publicly +# available versions of such operating systems available under the GNU General +# Public License 2.0 or later (whether in gold, beta or alpha form) causes +# such combination to be covered by the Licensed Patents. The patent license +# shall not apply to any other combinations which include the Software. NO +# hardware per se is licensed hereunder. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) 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. +# +################################################################################ + # # Makefile for the Intel(R) PRO/1000 ethernet driver # diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h --- a/drivers/net/e1000/e1000.h Sun Jun 2 18:44:56 2002 +++ b/drivers/net/e1000/e1000.h Sun Jun 2 18:44:56 2002 @@ -107,18 +107,21 @@ #include #include #include -#include +#include #include #ifdef NETIF_F_HW_VLAN_TX #include #endif +#define BAR_0 0 +#define PCI_DMA_64BIT 0xffffffffffffffffULL +#define PCI_DMA_32BIT 0x00000000ffffffffULL + + struct e1000_adapter; #include "e1000_hw.h" -#define BAR_0 0 - #if DBG #define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args) #else @@ -156,6 +159,7 @@ struct sk_buff *skb; uint64_t dma; unsigned long length; + unsigned long time_stamp; }; struct e1000_desc_ring { @@ -204,10 +208,13 @@ spinlock_t stats_lock; atomic_t irq_sem; +#ifdef ETHTOOL_PHYS_ID + struct timer_list blink_timer; + unsigned long led_status; +#endif + /* TX */ struct e1000_desc_ring tx_ring; - unsigned long trans_finish; - spinlock_t tx_lock; uint32_t txd_cmd; int max_data_per_txd; @@ -228,6 +235,9 @@ struct e1000_hw_stats stats; struct e1000_phy_info phy_info; struct e1000_phy_stats phy_stats; -}; + + + uint32_t pci_state[16]; +}; #endif /* _E1000_H_ */ diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c --- a/drivers/net/e1000/e1000_ethtool.c Sun Jun 2 18:44:57 2002 +++ b/drivers/net/e1000/e1000_ethtool.c Sun Jun 2 18:44:57 2002 @@ -75,7 +75,6 @@ #include "e1000.h" -#include #include extern char e1000_driver_name[]; @@ -83,7 +82,6 @@ extern int e1000_up(struct e1000_adapter *adapter); extern void e1000_down(struct e1000_adapter *adapter); -extern void e1000_enable_WOL(struct e1000_adapter *adapter); static void e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) @@ -128,7 +126,11 @@ SUPPORTED_Autoneg); ecmd->port = PORT_FIBRE; - ecmd->transceiver = XCVR_EXTERNAL; + + if(hw->mac_type >= e1000_82545) + ecmd->transceiver = XCVR_INTERNAL; + else + ecmd->transceiver = XCVR_EXTERNAL; } if(netif_carrier_ok(adapter->netdev)) { @@ -211,10 +213,38 @@ strncpy(drvinfo->version, e1000_driver_version, 32); strncpy(drvinfo->fw_version, "", 32); strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32); +#define E1000_REGS_LEN 32 + drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t); drvinfo->eedump_len = e1000_eeprom_size(&adapter->hw); } static void +e1000_ethtool_gregs(struct e1000_adapter *adapter, + struct ethtool_regs *regs, uint32_t *regs_buff) +{ + struct e1000_hw *hw = &adapter->hw; + + regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; + + regs_buff[0] = E1000_READ_REG(hw, CTRL); + regs_buff[1] = E1000_READ_REG(hw, STATUS); + + regs_buff[2] = E1000_READ_REG(hw, RCTL); + regs_buff[3] = E1000_READ_REG(hw, RDLEN); + regs_buff[4] = E1000_READ_REG(hw, RDH); + regs_buff[5] = E1000_READ_REG(hw, RDT); + regs_buff[6] = E1000_READ_REG(hw, RDTR); + + regs_buff[7] = E1000_READ_REG(hw, TCTL); + regs_buff[8] = E1000_READ_REG(hw, TDLEN); + regs_buff[9] = E1000_READ_REG(hw, TDH); + regs_buff[10] = E1000_READ_REG(hw, TDT); + regs_buff[11] = E1000_READ_REG(hw, TIDV); + + return; +} + +static void e1000_ethtool_geeprom(struct e1000_adapter *adapter, struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff) { @@ -228,7 +258,7 @@ if ((eeprom->offset + eeprom->len) > max_len) eeprom->len = (max_len - eeprom->offset); - for(i = 0; i < max_len; i++) + for(i = 0; i < (max_len >> 1); i++) e1000_read_eeprom(&adapter->hw, i, &eeprom_buff[i]); } @@ -236,27 +266,50 @@ e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) { struct e1000_hw *hw = &adapter->hw; - - if(hw->mac_type < e1000_82544) { + + switch(adapter->hw.device_id) { + case E1000_DEV_ID_82542: + case E1000_DEV_ID_82543GC_FIBER: + case E1000_DEV_ID_82543GC_COPPER: + case E1000_DEV_ID_82544EI_FIBER: + default: wol->supported = 0; wol->wolopts = 0; return; - } - wol->supported = WAKE_PHY | WAKE_UCAST | - WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; - - wol->wolopts = 0; - if(adapter->wol & E1000_WUFC_LNKC) - wol->wolopts |= WAKE_PHY; - if(adapter->wol & E1000_WUFC_EX) - wol->wolopts |= WAKE_UCAST; - if(adapter->wol & E1000_WUFC_MC) - wol->wolopts |= WAKE_MCAST; - if(adapter->wol & E1000_WUFC_BC) - wol->wolopts |= WAKE_BCAST; - if(adapter->wol & E1000_WUFC_MAG) - wol->wolopts |= WAKE_MAGIC; + case E1000_DEV_ID_82546EB_FIBER: + /* Wake events only supported on port A for dual fiber */ + if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) { + wol->supported = 0; + wol->wolopts = 0; + return; + } + /* Fall Through */ + + case E1000_DEV_ID_82544EI_COPPER: + case E1000_DEV_ID_82544GC_COPPER: + case E1000_DEV_ID_82544GC_LOM: + case E1000_DEV_ID_82540EM: + case E1000_DEV_ID_82540EM_LOM: + case E1000_DEV_ID_82545EM_COPPER: + case E1000_DEV_ID_82545EM_FIBER: + case E1000_DEV_ID_82546EB_COPPER: + wol->supported = WAKE_PHY | WAKE_UCAST | + WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; + + wol->wolopts = 0; + if(adapter->wol & E1000_WUFC_LNKC) + wol->wolopts |= WAKE_PHY; + if(adapter->wol & E1000_WUFC_EX) + wol->wolopts |= WAKE_UCAST; + if(adapter->wol & E1000_WUFC_MC) + wol->wolopts |= WAKE_MCAST; + if(adapter->wol & E1000_WUFC_BC) + wol->wolopts |= WAKE_BCAST; + if(adapter->wol & E1000_WUFC_MAG) + wol->wolopts |= WAKE_MAGIC; + return; + } } static int @@ -264,25 +317,95 @@ { struct e1000_hw *hw = &adapter->hw; - if(hw->mac_type < e1000_82544) + switch(adapter->hw.device_id) { + case E1000_DEV_ID_82542: + case E1000_DEV_ID_82543GC_FIBER: + case E1000_DEV_ID_82543GC_COPPER: + case E1000_DEV_ID_82544EI_FIBER: + default: return wol->wolopts ? -EOPNOTSUPP : 0; - adapter->wol = 0; + case E1000_DEV_ID_82546EB_FIBER: + /* Wake events only supported on port A for dual fiber */ + if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) + return wol->wolopts ? -EOPNOTSUPP : 0; + /* Fall Through */ + + case E1000_DEV_ID_82544EI_COPPER: + case E1000_DEV_ID_82544GC_COPPER: + case E1000_DEV_ID_82544GC_LOM: + case E1000_DEV_ID_82540EM: + case E1000_DEV_ID_82540EM_LOM: + case E1000_DEV_ID_82545EM_COPPER: + case E1000_DEV_ID_82545EM_FIBER: + case E1000_DEV_ID_82546EB_COPPER: + if(wol->wolopts & WAKE_ARP) + return -EOPNOTSUPP; + + adapter->wol = 0; + + if(wol->wolopts & WAKE_PHY) + adapter->wol |= E1000_WUFC_LNKC; + if(wol->wolopts & WAKE_UCAST) + adapter->wol |= E1000_WUFC_EX; + if(wol->wolopts & WAKE_MCAST) + adapter->wol |= E1000_WUFC_MC; + if(wol->wolopts & WAKE_BCAST) + adapter->wol |= E1000_WUFC_BC; + if(wol->wolopts & WAKE_MAGIC) + adapter->wol |= E1000_WUFC_MAG; + } + + return 0; +} + +#ifdef ETHTOOL_PHYS_ID - if(wol->wolopts & WAKE_PHY) - adapter->wol |= E1000_WUFC_LNKC; - if(wol->wolopts & WAKE_UCAST) - adapter->wol |= E1000_WUFC_EX; - if(wol->wolopts & WAKE_MCAST) - adapter->wol |= E1000_WUFC_MC; - if(wol->wolopts & WAKE_BCAST) - adapter->wol |= E1000_WUFC_BC; - if(wol->wolopts & WAKE_MAGIC) - adapter->wol |= E1000_WUFC_MAG; +/* toggle LED 4 times per second = 2 "blinks" per second */ +#define E1000_ID_INTERVAL (HZ/4) + +/* bit defines for adapter->led_status */ +#define E1000_LED_ON 0 + +static void +e1000_led_blink_callback(unsigned long data) +{ + struct e1000_adapter *adapter = (struct e1000_adapter *) data; + + if(test_and_change_bit(E1000_LED_ON, &adapter->led_status)) + e1000_led_off(&adapter->hw); + else + e1000_led_on(&adapter->hw); + + mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL); +} + +static int +e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id) +{ + if(!adapter->blink_timer.function) { + init_timer(&adapter->blink_timer); + adapter->blink_timer.function = e1000_led_blink_callback; + adapter->blink_timer.data = (unsigned long) adapter; + } + + e1000_setup_led(&adapter->hw); + mod_timer(&adapter->blink_timer, jiffies); + + set_current_state(TASK_INTERRUPTIBLE); + if(id->data) + schedule_timeout(id->data * HZ); + else + schedule_timeout(MAX_SCHEDULE_TIMEOUT); + + del_timer_sync(&adapter->blink_timer); + e1000_led_off(&adapter->hw); + clear_bit(E1000_LED_ON, &adapter->led_status); + e1000_cleanup_led(&adapter->hw); - e1000_enable_WOL(adapter); return 0; } +#endif /* ETHTOOL_PHYS_ID */ int e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) @@ -317,6 +440,22 @@ return -EFAULT; return 0; } + case ETHTOOL_GREGS: { + struct ethtool_regs regs = {ETHTOOL_GREGS}; + uint32_t regs_buff[E1000_REGS_LEN]; + + if(copy_from_user(®s, addr, sizeof(regs))) + return -EFAULT; + e1000_ethtool_gregs(adapter, ®s, regs_buff); + if(copy_to_user(addr, ®s, sizeof(regs))) + return -EFAULT; + + addr += offsetof(struct ethtool_regs, data); + if(copy_to_user(addr, regs_buff, regs.len)) + return -EFAULT; + + return 0; + } case ETHTOOL_NWAY_RST: { if(!capable(CAP_NET_ADMIN)) return -EPERM; @@ -324,6 +463,14 @@ e1000_up(adapter); return 0; } +#ifdef ETHTOOL_PHYS_ID + case ETHTOOL_PHYS_ID: { + struct ethtool_value id; + if(copy_from_user(&id, addr, sizeof(id))) + return -EFAULT; + return e1000_ethtool_led_blink(adapter, &id); + } +#endif /* ETHTOOL_PHYS_ID */ case ETHTOOL_GLINK: { struct ethtool_value link = {ETHTOOL_GLINK}; link.data = netif_carrier_ok(netdev); diff -Nru a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c --- a/drivers/net/e1000/e1000_hw.c Sun Jun 2 18:44:57 2002 +++ b/drivers/net/e1000/e1000_hw.c Sun Jun 2 18:44:57 2002 @@ -93,6 +93,7 @@ static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw); static void e1000_setup_eeprom(struct e1000_hw *hw); static void e1000_standby_eeprom(struct e1000_hw *hw); +static int32_t e1000_id_led_init(struct e1000_hw * hw); /****************************************************************************** * Reset the transmit and receive units; mask and clear all interrupts. @@ -197,9 +198,20 @@ uint32_t i; int32_t ret_val; uint16_t pci_cmd_word; + uint16_t pcix_cmd_word; + uint16_t pcix_stat_hi_word; + uint16_t cmd_mmrbc; + uint16_t stat_mmrbc; DEBUGFUNC("e1000_init_hw"); + /* Initialize Identification LED */ + ret_val = e1000_id_led_init(hw); + if(ret_val < 0) { + DEBUGOUT("Error Initializing Identification LED\n"); + return ret_val; + } + /* Set the Media Type and exit with error if it is not valid. */ if(hw->mac_type != e1000_82543) { /* tbi_compatibility is only valid on 82543 */ @@ -264,6 +276,21 @@ E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR); } + /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ + if(hw->bus_type == e1000_bus_type_pcix) { + e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); + e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word); + cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >> + PCIX_COMMAND_MMRBC_SHIFT; + stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> + PCIX_STATUS_HI_MMRBC_SHIFT; + if(cmd_mmrbc > stat_mmrbc) { + pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK; + pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; + e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); + } + } + /* Call a subroutine to configure the link and setup flow control. */ ret_val = e1000_setup_link(hw); @@ -541,6 +568,7 @@ */ if(hw->mac_type > e1000_82543) { ctrl |= E1000_CTRL_SLU; + ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, CTRL, ctrl); } else { ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU); @@ -2061,6 +2089,8 @@ if(hw->phy_id == M88E1000_I_PHY_ID) match = TRUE; break; case e1000_82540: + case e1000_82545: + case e1000_82546: if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE; break; default: @@ -2087,9 +2117,9 @@ DEBUGFUNC("e1000_phy_reset_dsp"); do { - if(e1000_write_phy_reg(hw, 29, 0x1d) < 0) break; - if(e1000_write_phy_reg(hw, 30, 0xc1) < 0) break; - if(e1000_write_phy_reg(hw, 30, 0x00) < 0) break; + if(e1000_write_phy_reg(hw, 29, 0x001d) < 0) break; + if(e1000_write_phy_reg(hw, 30, 0x00c1) < 0) break; + if(e1000_write_phy_reg(hw, 30, 0x0000) < 0) break; ret_val = 0; } while(0); @@ -2150,8 +2180,8 @@ M88E1000_PSSR_MDIX_SHIFT; if(phy_data & M88E1000_PSSR_1000MBS) { /* Cable Length Estimation and Local/Remote Receiver Informatoion - * are only valid at 1000 Mbps - */ + * are only valid at 1000 Mbps + */ phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> M88E1000_PSSR_CABLE_LENGTH_SHIFT); if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0) @@ -2521,6 +2551,13 @@ hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF); hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8); } + if((hw->mac_type == e1000_82546) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + if(hw->perm_mac_addr[5] & 0x01) + hw->perm_mac_addr[5] &= ~(0x01); + else + hw->perm_mac_addr[5] |= 0x01; + } for(i = 0; i < NODE_ADDRESS_SIZE; i++) hw->mac_addr[i] = hw->perm_mac_addr[i]; return 0; @@ -2785,6 +2822,74 @@ E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0); } +static int32_t +e1000_id_led_init(struct e1000_hw * hw) +{ + uint32_t ledctl; + const uint32_t ledctl_mask = 0x000000FF; + const uint32_t ledctl_on = E1000_LEDCTL_MODE_LED_ON; + const uint32_t ledctl_off = E1000_LEDCTL_MODE_LED_OFF; + uint16_t eeprom_data, i, temp; + const uint16_t led_mask = 0x0F; + + DEBUGFUNC("e1000_id_led_init"); + + if(hw->mac_type < e1000_82540) { + /* Nothing to do */ + return 0; + } + + ledctl = E1000_READ_REG(hw, LEDCTL); + hw->ledctl_default = ledctl; + hw->ledctl_mode1 = hw->ledctl_default; + hw->ledctl_mode2 = hw->ledctl_default; + + if(e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, &eeprom_data) < 0) { + DEBUGOUT("EEPROM Read Error\n"); + return -E1000_ERR_EEPROM; + } + if((eeprom_data== ID_LED_RESERVED_0000) || + (eeprom_data == ID_LED_RESERVED_FFFF)) eeprom_data = ID_LED_DEFAULT; + for(i = 0; i < 4; i++) { + temp = (eeprom_data >> (i << 2)) & led_mask; + switch(temp) { + case ID_LED_ON1_DEF2: + case ID_LED_ON1_ON2: + case ID_LED_ON1_OFF2: + hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); + hw->ledctl_mode1 |= ledctl_on << (i << 3); + break; + case ID_LED_OFF1_DEF2: + case ID_LED_OFF1_ON2: + case ID_LED_OFF1_OFF2: + hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); + hw->ledctl_mode1 |= ledctl_off << (i << 3); + break; + default: + /* Do nothing */ + break; + } + switch(temp) { + case ID_LED_DEF1_ON2: + case ID_LED_ON1_ON2: + case ID_LED_OFF1_ON2: + hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); + hw->ledctl_mode2 |= ledctl_on << (i << 3); + break; + case ID_LED_DEF1_OFF2: + case ID_LED_ON1_OFF2: + case ID_LED_OFF1_OFF2: + hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); + hw->ledctl_mode2 |= ledctl_off << (i << 3); + break; + default: + /* Do nothing */ + break; + } + } + return 0; +} + /****************************************************************************** * Prepares SW controlable LED for use and saves the current state of the LED. * @@ -2807,22 +2912,24 @@ case E1000_DEV_ID_82544GC_LOM: /* No setup necessary */ break; - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: + case E1000_DEV_ID_82545EM_FIBER: + case E1000_DEV_ID_82546EB_FIBER: ledctl = E1000_READ_REG(hw, LEDCTL); /* Save current LEDCTL settings */ - hw->ledctl = ledctl; - /* Turn off LED2 and LED3 */ - ledctl &= ~(E1000_LEDCTL_LED2_IVRT | - E1000_LEDCTL_LED2_BLINK | - E1000_LEDCTL_LED2_MODE_MASK); - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED2_MODE_SHIFT); - ledctl &= ~(E1000_LEDCTL_LED3_IVRT | - E1000_LEDCTL_LED3_BLINK | - E1000_LEDCTL_LED3_MODE_MASK); - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED3_MODE_SHIFT); + hw->ledctl_default = ledctl; + /* Turn off LED0 */ + ledctl &= ~(E1000_LEDCTL_LED0_IVRT | + E1000_LEDCTL_LED0_BLINK | + E1000_LEDCTL_LED0_MODE_MASK); + ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT); E1000_WRITE_REG(hw, LEDCTL, ledctl); break; + case E1000_DEV_ID_82540EM: + case E1000_DEV_ID_82540EM_LOM: + case E1000_DEV_ID_82545EM_COPPER: + case E1000_DEV_ID_82546EB_COPPER: + E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); + break; default: DEBUGOUT("Invalid device ID\n"); return -E1000_ERR_CONFIG; @@ -2852,8 +2959,12 @@ break; case E1000_DEV_ID_82540EM: case E1000_DEV_ID_82540EM_LOM: + case E1000_DEV_ID_82545EM_COPPER: + case E1000_DEV_ID_82545EM_FIBER: + case E1000_DEV_ID_82546EB_COPPER: + case E1000_DEV_ID_82546EB_FIBER: /* Restore LEDCTL settings */ - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl); + E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default); break; default: DEBUGOUT("Invalid device ID\n"); @@ -2871,7 +2982,6 @@ e1000_led_on(struct e1000_hw *hw) { uint32_t ctrl; - uint32_t ledctl; DEBUGFUNC("e1000_led_on"); @@ -2889,6 +2999,8 @@ case E1000_DEV_ID_82544EI_COPPER: case E1000_DEV_ID_82544GC_COPPER: case E1000_DEV_ID_82544GC_LOM: + case E1000_DEV_ID_82545EM_FIBER: + case E1000_DEV_ID_82546EB_FIBER: ctrl = E1000_READ_REG(hw, CTRL); /* Clear SW Defineable Pin 0 to turn on the LED */ ctrl &= ~E1000_CTRL_SWDPIN0; @@ -2897,11 +3009,9 @@ break; case E1000_DEV_ID_82540EM: case E1000_DEV_ID_82540EM_LOM: - ledctl = E1000_READ_REG(hw, LEDCTL); - /* Set LED 3 mode to on */ - ledctl &= ~E1000_LEDCTL_LED3_MODE_MASK; - ledctl |= (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED3_MODE_SHIFT); - E1000_WRITE_REG(hw, LEDCTL, ledctl); + case E1000_DEV_ID_82545EM_COPPER: + case E1000_DEV_ID_82546EB_COPPER: + E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2); break; default: DEBUGOUT("Invalid device ID\n"); @@ -2919,7 +3029,6 @@ e1000_led_off(struct e1000_hw *hw) { uint32_t ctrl; - uint32_t ledctl; DEBUGFUNC("e1000_led_off"); @@ -2937,6 +3046,8 @@ case E1000_DEV_ID_82544EI_COPPER: case E1000_DEV_ID_82544GC_COPPER: case E1000_DEV_ID_82544GC_LOM: + case E1000_DEV_ID_82545EM_FIBER: + case E1000_DEV_ID_82546EB_FIBER: ctrl = E1000_READ_REG(hw, CTRL); /* Set SW Defineable Pin 0 to turn off the LED */ ctrl |= E1000_CTRL_SWDPIN0; @@ -2945,11 +3056,9 @@ break; case E1000_DEV_ID_82540EM: case E1000_DEV_ID_82540EM_LOM: - ledctl = E1000_READ_REG(hw, LEDCTL); - /* Set LED 3 mode to off */ - ledctl &= ~E1000_LEDCTL_LED3_MODE_MASK; - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED3_MODE_SHIFT); - E1000_WRITE_REG(hw, LEDCTL, ledctl); + case E1000_DEV_ID_82545EM_COPPER: + case E1000_DEV_ID_82546EB_COPPER: + E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); break; default: DEBUGOUT("Invalid device ID\n"); diff -Nru a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h --- a/drivers/net/e1000/e1000_hw.h Sun Jun 2 18:44:57 2002 +++ b/drivers/net/e1000/e1000_hw.h Sun Jun 2 18:44:57 2002 @@ -92,6 +92,8 @@ e1000_82543, e1000_82544, e1000_82540, + e1000_82545, + e1000_82546, e1000_num_macs } e1000_mac_type; @@ -260,6 +262,7 @@ void e1000_update_adaptive(struct e1000_hw *hw); void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, uint32_t frame_len, uint8_t * mac_addr); void e1000_get_bus_info(struct e1000_hw *hw); +void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); /* PCI Device IDs */ @@ -272,7 +275,11 @@ #define E1000_DEV_ID_82544GC_LOM 0x100D #define E1000_DEV_ID_82540EM 0x100E #define E1000_DEV_ID_82540EM_LOM 0x1015 -#define NUM_DEV_IDS 9 +#define E1000_DEV_ID_82545EM_COPPER 0x100F +#define E1000_DEV_ID_82545EM_FIBER 0x1011 +#define E1000_DEV_ID_82546EB_COPPER 0x1010 +#define E1000_DEV_ID_82546EB_FIBER 0x1012 +#define NUM_DEV_IDS 13 #define NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 @@ -882,7 +889,9 @@ uint32_t num_mc_addrs; uint32_t collision_delta; uint32_t tx_packet_delta; - uint32_t ledctl; + uint32_t ledctl_default; + uint32_t ledctl_mode1; + uint32_t ledctl_mode2; uint16_t autoneg_advertised; uint16_t pci_cmd_word; uint16_t fc_high_water; @@ -1324,10 +1333,28 @@ #define EEPROM_EWDS_OPCODE 0x10 /* EERPOM erast/write disable */ /* EEPROM Word Offsets */ -#define EEPROM_INIT_CONTROL1_REG 0x000A -#define EEPROM_INIT_CONTROL2_REG 0x000F -#define EEPROM_FLASH_VERSION 0x0032 -#define EEPROM_CHECKSUM_REG 0x003F +#define EEPROM_ID_LED_SETTINGS 0x0004 +#define EEPROM_INIT_CONTROL1_REG 0x000A +#define EEPROM_INIT_CONTROL2_REG 0x000F +#define EEPROM_FLASH_VERSION 0x0032 +#define EEPROM_CHECKSUM_REG 0x003F + +/* Word definitions for ID LED Settings */ +#define ID_LED_RESERVED_0000 0x0000 +#define ID_LED_RESERVED_FFFF 0xFFFF +#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ + (ID_LED_OFF1_OFF2 << 8) | \ + (ID_LED_DEF1_DEF2 << 4) | \ + (ID_LED_DEF1_DEF2)) +#define ID_LED_DEF1_DEF2 0x1 +#define ID_LED_DEF1_ON2 0x2 +#define ID_LED_DEF1_OFF2 0x3 +#define ID_LED_ON1_DEF2 0x4 +#define ID_LED_ON1_ON2 0x5 +#define ID_LED_ON1_OFF2 0x6 +#define ID_LED_OFF1_DEF2 0x7 +#define ID_LED_OFF1_ON2 0x8 +#define ID_LED_OFF1_OFF2 0x9 /* Mask bits for fields in Word 0x0a of the EEPROM */ #define EEPROM_WORD0A_ILOS 0x0010 @@ -1413,6 +1440,16 @@ #define FC_DEFAULT_HI_THRESH (0x8000) /* 32KB */ #define FC_DEFAULT_LO_THRESH (0x4000) /* 16KB */ #define FC_DEFAULT_TX_TIMER (0x100) /* ~130 us */ + +/* PCIX Config space */ +#define PCIX_COMMAND_REGISTER 0xE6 +#define PCIX_STATUS_REGISTER_LO 0xE8 +#define PCIX_STATUS_REGISTER_HI 0xEA + +#define PCIX_COMMAND_MMRBC_MASK 0x000C +#define PCIX_COMMAND_MMRBC_SHIFT 0x2 +#define PCIX_STATUS_HI_MMRBC_MASK 0x0060 +#define PCIX_STATUS_HI_MMRBC_SHIFT 0x5 /* The number of bits that we need to shift right to move the "pause" diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c --- a/drivers/net/e1000/e1000_main.c Sun Jun 2 18:44:57 2002 +++ b/drivers/net/e1000/e1000_main.c Sun Jun 2 18:44:57 2002 @@ -76,7 +76,7 @@ char e1000_driver_name[] = "e1000"; char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -char e1000_driver_version[] = "4.2.8"; +char e1000_driver_version[] = "4.2.17-k1"; char e1000_copyright[] = "Copyright (c) 1999-2002 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table @@ -114,6 +114,10 @@ {0x8086, 0x100C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x100E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x100F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* required last entry */ {0,} }; @@ -126,7 +130,7 @@ "IBM Mobile, Desktop & Server Adapters" }; -/* e1000_main.c Function Prototypes */ +/* Local Function Prototypes */ int e1000_up(struct e1000_adapter *adapter); void e1000_down(struct e1000_adapter *adapter); @@ -169,13 +173,24 @@ static inline void e1000_rx_checksum(struct e1000_adapter *adapter, struct e1000_rx_desc *rx_desc, struct sk_buff *skb); -void e1000_enable_WOL(struct e1000_adapter *adapter); #ifdef NETIF_F_HW_VLAN_TX static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); #endif +static int e1000_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); +static int e1000_suspend(struct pci_dev *pdev, uint32_t state); +#ifdef CONFIG_PM +static int e1000_resume(struct pci_dev *pdev); +#endif + +struct notifier_block e1000_notifier = { + notifier_call: e1000_notify_reboot, + next: NULL, + priority: 0 +}; + /* Exported from other modules */ extern void e1000_check_options(struct e1000_adapter *adapter); @@ -189,8 +204,10 @@ probe: e1000_probe, remove: __devexit_p(e1000_remove), /* Power Managment Hooks */ - suspend: NULL, - resume: NULL +#ifdef CONFIG_PM + suspend: e1000_suspend, + resume: e1000_resume +#endif }; MODULE_AUTHOR("Intel Corporation, "); @@ -207,12 +224,16 @@ static int __init e1000_init_module(void) { + int ret; printk(KERN_INFO "%s - version %s\n", e1000_driver_string, e1000_driver_version); printk(KERN_INFO "%s\n", e1000_copyright); - return pci_module_init(&e1000_driver); + ret = pci_module_init(&e1000_driver); + if(ret >= 0) + register_reboot_notifier(&e1000_notifier); + return ret; } module_init(e1000_init_module); @@ -227,6 +248,7 @@ static void __exit e1000_exit_module(void) { + unregister_reboot_notifier(&e1000_notifier); pci_unregister_driver(&e1000_driver); } @@ -290,11 +312,11 @@ adapter->hw.fc = adapter->hw.original_fc; e1000_reset_hw(&adapter->hw); + if(adapter->hw.mac_type >= e1000_82544) + E1000_WRITE_REG(&adapter->hw, WUC, 0); e1000_init_hw(&adapter->hw); e1000_reset_adaptive(&adapter->hw); e1000_phy_get_info(&adapter->hw, &adapter->phy_info); - - e1000_enable_WOL(adapter); } /** @@ -324,10 +346,10 @@ if((i = pci_enable_device(pdev))) return i; - if(!(i = pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff))) { + if(!(i = pci_set_dma_mask(pdev, PCI_DMA_64BIT))) { pci_using_dac = 1; } else { - if((i = pci_set_dma_mask(pdev, (u64) 0xffffffff))) { + if((i = pci_set_dma_mask(pdev, PCI_DMA_32BIT))) { E1000_ERR("No usable DMA configuration, aborting\n"); return i; } @@ -403,8 +425,10 @@ /* make sure the EEPROM is good */ - if(e1000_validate_eeprom_checksum(&adapter->hw) < 0) + if(e1000_validate_eeprom_checksum(&adapter->hw) < 0) { + printk(KERN_ERR "The EEPROM Checksum Is Not Valid\n"); goto err_eeprom; + } /* copy the MAC address out of the EEPROM */ @@ -437,7 +461,7 @@ register_netdev(netdev); /* we're going to reset, so assume we have no link for now */ - + netif_carrier_off(netdev); netif_stop_queue(netdev); @@ -445,6 +469,15 @@ e1000_check_options(adapter); e1000_proc_dev_setup(adapter); + /* Initial Wake on LAN setting + * If APM wake is enabled in the EEPROM, + * enable the ACPI Magic Packet filter + */ + + if((adapter->hw.mac_type >= e1000_82544) && + (E1000_READ_REG(&adapter->hw, WUC) & E1000_WUC_APME)) + adapter->wol |= E1000_WUFC_MAG; + /* reset the hardware with the new settings */ e1000_reset(adapter); @@ -555,6 +588,14 @@ case E1000_DEV_ID_82540EM: hw->mac_type = e1000_82540; break; + case E1000_DEV_ID_82545EM_COPPER: + case E1000_DEV_ID_82545EM_FIBER: + hw->mac_type = e1000_82545; + break; + case E1000_DEV_ID_82546EB_COPPER: + case E1000_DEV_ID_82546EB_FIBER: + hw->mac_type = e1000_82546; + break; default: /* should never have loaded on this device */ BUG(); @@ -590,7 +631,6 @@ hw->adaptive_ifs = TRUE; atomic_set(&adapter->irq_sem, 1); - spin_lock_init(&adapter->tx_lock); spin_lock_init(&adapter->stats_lock); } @@ -715,7 +755,7 @@ uint32_t tdlen = adapter->tx_ring.count * sizeof(struct e1000_tx_desc); uint32_t tctl, tipg; - E1000_WRITE_REG(&adapter->hw, TDBAL, (tdba & 0x00000000FFFFFFFF)); + E1000_WRITE_REG(&adapter->hw, TDBAL, (tdba & 0x00000000ffffffffULL)); E1000_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32)); E1000_WRITE_REG(&adapter->hw, TDLEN, tdlen); @@ -752,7 +792,7 @@ tctl = E1000_READ_REG(&adapter->hw, TCTL); - tctl &= ~E1000_TCTL_CT; + tctl &= ~E1000_TCTL_CT; tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); @@ -875,7 +915,7 @@ /* set the Receive Delay Timer Register */ - if(adapter->hw.mac_type == e1000_82540) { + if(adapter->hw.mac_type >= e1000_82540) { E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_int_delay); E1000_WRITE_REG(&adapter->hw, RDTR, 64); @@ -891,7 +931,7 @@ /* Setup the Base and Length of the Rx Descriptor Ring */ - E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000FFFFFFFF)); + E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000ffffffffULL)); E1000_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32)); E1000_WRITE_REG(&adapter->hw, RDLEN, rdlen); @@ -1212,6 +1252,8 @@ { struct e1000_adapter *adapter = (struct e1000_adapter *) data; struct net_device *netdev = adapter->netdev; + struct e1000_desc_ring *txdr = &adapter->tx_ring; + int i; e1000_check_for_link(&adapter->hw); @@ -1228,7 +1270,6 @@ "Full Duplex" : "Half Duplex"); netif_carrier_on(netdev); - adapter->trans_finish = jiffies; netif_wake_queue(netdev); mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ); } @@ -1248,6 +1289,13 @@ e1000_update_stats(adapter); e1000_update_adaptive(&adapter->hw); + /* Early detection of hung controller */ + i = txdr->next_to_clean; + if(txdr->buffer_info[i].dma && + time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) && + !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF)) + netif_stop_queue(netdev); + /* Reset the timer */ mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); } @@ -1310,6 +1358,7 @@ skb->data + offset, size, PCI_DMA_TODEVICE); + tx_ring->buffer_info[i].time_stamp = jiffies; len -= size; offset += size; @@ -1388,20 +1437,11 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct e1000_adapter *adapter = netdev->priv; - unsigned long flags; int tx_flags = 0, count; int f; - if(time_after(netdev->trans_start, adapter->trans_finish + HZ) && - !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF)) { - - adapter->trans_finish = jiffies; - netif_stop_queue(netdev); - return 1; - } - count = TXD_USE_COUNT(skb->len - skb->data_len, adapter->max_data_per_txd); for(f = 0; f < skb_shinfo(skb)->nr_frags; f++) @@ -1410,14 +1450,10 @@ if(skb->ip_summed == CHECKSUM_HW) count++; - spin_lock_irqsave(&adapter->tx_lock, flags); - e1000_clean_tx_irq(adapter); if(E1000_DESC_UNUSED(&adapter->tx_ring) < count) { netif_stop_queue(netdev); - spin_unlock_irqrestore(&adapter->tx_lock, flags); return 1; } - spin_unlock_irqrestore(&adapter->tx_lock, flags); if(e1000_tx_csum(adapter, skb)) tx_flags |= E1000_TX_FLAGS_CSUM; @@ -1428,7 +1464,7 @@ tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); } #endif - + count = e1000_tx_map(adapter, skb); e1000_tx_queue(adapter, count, tx_flags); @@ -1701,12 +1737,7 @@ } e1000_clean_rx_irq(adapter); - - if((icr & E1000_ICR_TXDW) && spin_trylock(&adapter->tx_lock)) { - e1000_clean_tx_irq(adapter); - spin_unlock(&adapter->tx_lock); - } - + e1000_clean_tx_irq(adapter); i--; } @@ -1753,8 +1784,6 @@ i = (i + 1) % tx_ring->count; tx_desc = E1000_TX_DESC(*tx_ring, i); - - adapter->trans_finish = jiffies; } tx_ring->next_to_clean = i; @@ -1893,9 +1922,6 @@ int reserve_len; int i; - if(!netif_running(netdev)) - return; - reserve_len = 2; i = rx_ring->next_to_use; @@ -1991,32 +2017,16 @@ } } -/** - * e1000_enable_WOL - Wake On Lan Support (Magic Pkt) - * @adapter: Adapter structure - **/ - void -e1000_enable_WOL(struct e1000_adapter *adapter) +e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) { - uint32_t wuc; - - if(adapter->hw.mac_type < e1000_82544) - return; - - if(adapter->wol) { - wuc = E1000_WUC_APME | E1000_WUC_PME_EN | - E1000_WUC_PME_STATUS | E1000_WUC_APMPME; - - E1000_WRITE_REG(&adapter->hw, WUC, wuc); + struct e1000_adapter *adapter = hw->back; - E1000_WRITE_REG(&adapter->hw, WUFC, adapter->wol); - } + pci_read_config_word(adapter->pdev, reg, value); } void -e1000_write_pci_cfg(struct e1000_hw *hw, - uint32_t reg, uint16_t *value) +e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) { struct e1000_adapter *adapter = hw->back; @@ -2086,10 +2096,10 @@ uint32_t vfta, index; e1000_irq_disable(adapter); - + if(adapter->vlgrp) adapter->vlgrp->vlan_devices[vid] = NULL; - + e1000_irq_enable(adapter); /* remove VID from filter table*/ @@ -2098,6 +2108,95 @@ vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); vfta &= ~(1 << (vid & 0x1F)); e1000_write_vfta(&adapter->hw, index, vfta); +} +#endif + +static int +e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) +{ + struct pci_dev *pdev = NULL; + + switch(event) { + case SYS_DOWN: + case SYS_HALT: + case SYS_POWER_OFF: + pci_for_each_dev(pdev) { + if(pci_dev_driver(pdev) == &e1000_driver) + e1000_suspend(pdev, 3); + } + } + return NOTIFY_DONE; +} + +static int +e1000_suspend(struct pci_dev *pdev, uint32_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev->priv; + uint32_t ctrl, ctrl_ext, rctl; + + netif_device_detach(netdev); + + if(netif_running(netdev)) + e1000_down(adapter); + + if(adapter->wol) { + e1000_setup_rctl(adapter); + e1000_set_multi(netdev); + + if(adapter->wol & E1000_WUFC_MC) { + rctl = E1000_READ_REG(&adapter->hw, RCTL); + rctl |= E1000_RCTL_MPE; + E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + } + + if(adapter->hw.media_type == e1000_media_type_fiber) { + #define E1000_CTRL_ADVD3WUC 0x00100000 + ctrl = E1000_READ_REG(&adapter->hw, CTRL); + ctrl |= E1000_CTRL_ADVD3WUC; + E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); + + ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; + E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext); + } + + E1000_WRITE_REG(&adapter->hw, WUC, 0); + E1000_WRITE_REG(&adapter->hw, WUFC, adapter->wol); + pci_enable_wake(pdev, 3, 1); + } else { + E1000_WRITE_REG(&adapter->hw, WUC, 0); + E1000_WRITE_REG(&adapter->hw, WUFC, 0); + pci_enable_wake(pdev, 3, 0); + } + + pci_save_state(pdev, adapter->pci_state); + pci_set_power_state(pdev, 3); + + return 0; +} + +#ifdef CONFIG_PM +static int +e1000_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev->priv; + + pci_set_power_state(pdev, 0); + pci_restore_state(pdev, adapter->pci_state); + pci_enable_wake(pdev, 0, 0); + + /* Clear the wakeup status bits */ + + E1000_WRITE_REG(&adapter->hw, WUS, ~0); + + if(netif_running(netdev)) + e1000_up(adapter); + + netif_device_attach(netdev); + + return 0; } #endif diff -Nru a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h --- a/drivers/net/e1000/e1000_osdep.h Sun Jun 2 18:44:56 2002 +++ b/drivers/net/e1000/e1000_osdep.h Sun Jun 2 18:44:56 2002 @@ -86,12 +86,14 @@ #include #define usec_delay(x) udelay(x) +#ifndef msec_delay #define msec_delay(x) do { if(in_interrupt()) { \ mdelay(x); \ } else { \ set_current_state(TASK_UNINTERRUPTIBLE); \ schedule_timeout((x * HZ)/1000); \ } } while(0) +#endif #define PCI_COMMAND_REGISTER PCI_COMMAND #define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c --- a/drivers/net/eepro100.c Sun Jun 2 18:44:58 2002 +++ b/drivers/net/eepro100.c Sun Jun 2 18:44:58 2002 @@ -524,10 +524,8 @@ static int eepro100_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static void eepro100_remove_one (struct pci_dev *pdev); -#ifdef CONFIG_PM static int eepro100_suspend (struct pci_dev *pdev, u32 state); static int eepro100_resume (struct pci_dev *pdev); -#endif static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len); static int mdio_read(long ioaddr, int phy_id, int location); diff -Nru a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c --- a/drivers/net/pcmcia/com20020_cs.c Sun Jun 2 18:44:57 2002 +++ b/drivers/net/pcmcia/com20020_cs.c Sun Jun 2 18:44:57 2002 @@ -122,6 +122,7 @@ MODULE_PARM(irq_mask, "i"); MODULE_PARM(irq_list, "1-4i"); +MODULE_LICENSE("GPL"); /*====================================================================*/ diff -Nru a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c --- a/drivers/net/pcnet32.c Sun Jun 2 18:44:57 2002 +++ b/drivers/net/pcnet32.c Sun Jun 2 18:44:57 2002 @@ -845,8 +845,9 @@ if (lp->options == (PCNET32_PORT_FD | PCNET32_PORT_AUI)) val |= 2; } else if (lp->options & PCNET32_PORT_ASEL) { - /* workaround for xSeries250 */ - val |= 3; + /* workaround of xSeries250, turn on for 79C975 only */ + i = ((lp->a.read_csr(ioaddr, 88) | (lp->a.read_csr(ioaddr,89) << 16)) >> 12) & 0xffff; + if (i == 0x2627) val |= 3; } lp->a.write_bcr (ioaddr, 9, val); } diff -Nru a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c --- a/drivers/net/tulip/de4x5.c Sun Jun 2 18:44:56 2002 +++ b/drivers/net/tulip/de4x5.c Sun Jun 2 18:44:56 2002 @@ -866,7 +866,7 @@ ** offsets in the PCI and EISA boards. Also note that the ethernet address ** PROM is accessed differently. */ -static struct bus_type { +static struct de4x5_bus_type { int bus; int bus_num; int device; @@ -967,10 +967,10 @@ static int test_ans(struct net_device *dev, s32 irqs, s32 irq_mask, s32 msec); static int test_tp(struct net_device *dev, s32 msec); static int EISA_signature(char *name, s32 eisa_id); -static int PCI_signature(char *name, struct bus_type *lp); +static int PCI_signature(char *name, struct de4x5_bus_type *lp); static void DevicePresent(u_long iobase); static void enet_addr_rst(u_long aprom_addr); -static int de4x5_bad_srom(struct bus_type *lp); +static int de4x5_bad_srom(struct de4x5_bus_type *lp); static short srom_rd(u_long address, u_char offset); static void srom_latch(u_int command, u_long address); static void srom_command(u_int command, u_long address); @@ -998,7 +998,7 @@ static int get_hw_addr(struct net_device *dev); static void srom_repair(struct net_device *dev, int card); static int test_bad_enet(struct net_device *dev, int status); -static int an_exception(struct bus_type *lp); +static int an_exception(struct de4x5_bus_type *lp); #if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__) static void eisa_probe(struct net_device *dev, u_long iobase); #endif @@ -1143,7 +1143,7 @@ static int __init de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev) { - struct bus_type *lp = &bus; + struct de4x5_bus_type *lp = &bus; int i, status=0; char *tmp; @@ -2105,7 +2105,7 @@ u_short vendor; u32 cfid; u_long iobase; - struct bus_type *lp = &bus; + struct de4x5_bus_type *lp = &bus; char name[DE4X5_STRLEN]; if (lastEISA == MAX_EISA_SLOTS) return;/* No more EISA devices to search */ @@ -2186,7 +2186,7 @@ u_short vendor, index, status; u_int irq = 0, device, class = DE4X5_CLASS_CODE; u_long iobase = 0; /* Clear upper 32 bits in Alphas */ - struct bus_type *lp = &bus; + struct de4x5_bus_type *lp = &bus; if (lastPCI == NO_MORE_PCI) return; @@ -2299,7 +2299,7 @@ u_int irq = 0, device; u_long iobase = 0; /* Clear upper 32 bits in Alphas */ int i, j; - struct bus_type *lp = &bus; + struct de4x5_bus_type *lp = &bus; struct list_head *walk = &dev->bus_list; for (walk = walk->next; walk != &dev->bus_list; walk = walk->next) { @@ -3992,7 +3992,7 @@ ** Look for a particular board name in the PCI configuration space */ static int -PCI_signature(char *name, struct bus_type *lp) +PCI_signature(char *name, struct de4x5_bus_type *lp) { static c_char *de4x5_signatures[] = DE4X5_SIGNATURE; int i, status = 0, siglen = sizeof(de4x5_signatures)/sizeof(c_char *); @@ -4041,7 +4041,7 @@ DevicePresent(u_long aprom_addr) { int i, j=0; - struct bus_type *lp = &bus; + struct de4x5_bus_type *lp = &bus; if (lp->chipset == DC21040) { if (lp->bus == EISA) { @@ -4122,7 +4122,7 @@ u_long iobase = dev->base_addr; int broken, i, k, tmp, status = 0; u_short j,chksum; - struct bus_type *lp = &bus; + struct de4x5_bus_type *lp = &bus; broken = de4x5_bad_srom(lp); @@ -4203,7 +4203,7 @@ ** didn't seem to work here...? */ static int -de4x5_bad_srom(struct bus_type *lp) +de4x5_bad_srom(struct de4x5_bus_type *lp) { int i, status = 0; @@ -4237,7 +4237,7 @@ static void srom_repair(struct net_device *dev, int card) { - struct bus_type *lp = &bus; + struct de4x5_bus_type *lp = &bus; switch(card) { case SMC: @@ -4258,7 +4258,7 @@ static int test_bad_enet(struct net_device *dev, int status) { - struct bus_type *lp = &bus; + struct de4x5_bus_type *lp = &bus; int i, tmp; for (tmp=0,i=0; idev_addr[i]; @@ -4291,7 +4291,7 @@ ** List of board exceptions with correctly wired IRQs */ static int -an_exception(struct bus_type *lp) +an_exception(struct de4x5_bus_type *lp) { if ((*(u_short *)lp->srom.sub_vendor_id == 0x00c0) && (*(u_short *)lp->srom.sub_system_id == 0x95e0)) { diff -Nru a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c --- a/drivers/net/wan/dscc4.c Sun Jun 2 18:44:56 2002 +++ b/drivers/net/wan/dscc4.c Sun Jun 2 18:44:56 2002 @@ -204,7 +204,7 @@ dma_addr_t iqtx_dma; dma_addr_t iqrx_dma; - volatile u32 scc_regs[SCC_REGISTERS_MAX]; /* Cf errata DS5 p.4 */ + u32 scc_regs[SCC_REGISTERS_MAX]; /* Cf errata DS5 p.4 */ struct timer_list timer; @@ -356,10 +356,10 @@ u32 state; /* Cf scc_writel for concern regarding thread-safety */ - state = dpriv->scc_regs[offset]; + state = dpriv->scc_regs[offset >> 2]; state &= ~mask; state |= value; - dpriv->scc_regs[offset] = state; + dpriv->scc_regs[offset >> 2] = state; writel(state, dev->base_addr + SCC_REG_START(dpriv) + offset); } @@ -370,13 +370,13 @@ * Thread-UNsafe. * As of 2002/02/16, there are no thread racing for access. */ - dpriv->scc_regs[offset] = bits; + dpriv->scc_regs[offset >> 2] = bits; writel(bits, dev->base_addr + SCC_REG_START(dpriv) + offset); } static inline u32 scc_readl(struct dscc4_dev_priv *dpriv, int offset) { - return dpriv->scc_regs[offset]; + return dpriv->scc_regs[offset >> 2]; } static u32 scc_readl_star(struct dscc4_dev_priv *dpriv, struct net_device *dev) diff -Nru a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c --- a/drivers/net/wireless/airo.c Sun Jun 2 18:44:56 2002 +++ b/drivers/net/wireless/airo.c Sun Jun 2 18:44:56 2002 @@ -12,8 +12,8 @@ (C) 1999 Benjamin Reed. All Rights Reserved. Permission to use code in the Developer's manual was granted for this driver by Aironet. Major code contributions were received from Javier Achirica - and Jean Tourrilhes . Code was also integrated from - the Cisco Aironet driver for Linux. + and Jean Tourrilhes . + Code was also integrated from the Cisco Aironet driver for Linux. ======================================================================*/ @@ -46,7 +46,7 @@ #include #ifdef CONFIG_PCI -static struct pci_device_id card_ids[] = __devinitdata { +static struct pci_device_id card_ids[] __devinitdata = { { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, }, { 0x14b9, 0x4500, PCI_ANY_ID, PCI_ANY_ID }, { 0x14b9, 0x4800, PCI_ANY_ID, PCI_ANY_ID, }, @@ -70,13 +70,11 @@ /* Include Wireless Extension definition and check version - Jean II */ #include #define WIRELESS_SPY // enable iwspy support -#if WIRELESS_EXT < 9 -#warning "Wireless extension v9 or newer required - please upgrade your kernel" -#undef WIRELESS_EXT -#undef WIRELESS_SPY -#endif -#define CISCO_EXT // enable Cisco extensions +#if WIRELESS_EXT > 12 +#include // New driver API +#endif /* WIRELESS_EXT > 12 */ +#define CISCO_EXT // enable Cisco extensions #ifdef CISCO_EXT #include #endif @@ -193,6 +191,12 @@ #ifndef RUN_AT #define RUN_AT(x) (jiffies+(x)) #endif +#ifndef PDE +static inline struct proc_dir_entry *PDE(const struct inode *inode) +{ + return inode->u.generic_ip; +} +#endif /* These variables are for insmod, since it seems that the rates @@ -215,6 +219,8 @@ the bap, needed on some older cards and buses. */ static int adhoc; +static int probe = 1; + static int proc_uid /* = 0 */; static int proc_gid /* = 0 */; @@ -249,6 +255,8 @@ Older cards used to be limited to 2mbs (4)."); MODULE_PARM(adhoc, "i"); MODULE_PARM_DESC(adhoc, "If non-zero, the card will start in adhoc mode."); +MODULE_PARM(probe, "i"); +MODULE_PARM_DESC(probe, "If zero, the driver won't start the card."); MODULE_PARM(proc_uid, "i"); MODULE_PARM_DESC(proc_uid, "The uid that the /proc files will belong to."); @@ -259,8 +267,6 @@ MODULE_PARM(proc_perm, "i"); MODULE_PARM_DESC(proc_perm, "The permission bits of the files in /proc"); -#include - /* This is a kind of sloppy hack to get this information to OUT4500 and IN4500. I would be extremely interested in the situation where this doesnt work though!!! */ @@ -276,13 +282,21 @@ #define MAC_ENABLE 0x0001 #define MAC_DISABLE 0x0002 #define CMD_LOSE_SYNC 0x0003 /* Not sure what this does... */ +#define CMD_MAGIC_PKT 0x0006 #define CMD_ACCESS 0x0021 #define CMD_ALLOCATETX 0x000a #define CMD_TRANSMIT 0x000b +#define CMD_DEALLOCATETX 0x000c #define HOSTSLEEP 0x85 #define CMD_SETMODE 0x0009 #define CMD_ENABLEAUX 0x0111 #define CMD_SOFTRESET 0x0004 +#define CMD_ALLOCBUF 0x0028 +#define CMD_PSPNODES 0x0030 +#define CMD_SETPHYREG 0x003e +#define CMD_TXTEST 0x003f +#define CMD_READCFG 0x0008 +#define CMD_SAVECFG 0x0108 #define CMD_LISTBSS 0x0103 /* Registers */ @@ -335,8 +349,14 @@ #define EV_LINK 0x80 #define EV_AWAKE 0x100 #define EV_UNKNOWN 0x800 +#define EV_MIC 0x1000 /* Message Integrity Check Interrupt */ #define STATUS_INTS ( EV_AWAKE | EV_LINK | EV_TXEXC | EV_TX | EV_RX) -#define IGNORE_INTS ( EV_CMD | EV_UNKNOWN) + +#ifdef CHECK_UNKNOWN_INTS +#define IGNORE_INTS ( EV_MIC | EV_CMD | EV_UNKNOWN) +#else +#define IGNORE_INTS (~STATUS_INTS) +#endif /* The RIDs */ #define RID_CAPABILITIES 0xFF00 @@ -359,7 +379,9 @@ #define RID_LEAPUSERNAME 0xFF23 #define RID_LEAPPASSWORD 0xFF24 #define RID_STATUS 0xFF50 -#define RID_UNKNOWN52 0xFF52 +#define RID_BEACON_HST 0xFF51 +#define RID_BUSY_HST 0xFF52 +#define RID_RETRIES_HST 0xFF53 #define RID_UNKNOWN54 0xFF54 #define RID_UNKNOWN55 0xFF55 #define RID_UNKNOWN56 0xFF56 @@ -569,7 +591,9 @@ u16 currentXmitRate; u16 apDevExtensions; u16 normalizedSignalStrength; - u16 _reserved[10]; + u16 _reserved1; + u8 apIP[4]; + u16 _reserved[7]; } StatusRid; typedef struct { @@ -676,6 +700,10 @@ #else /* SIOCIWFIRSTPRIV */ #define SIOCIWFIRSTPRIV SIOCDEVPRIVATE #endif /* SIOCIWFIRSTPRIV */ +/* This may be wrong. When using the new SIOCIWFIRSTPRIV range, we probably + * should use only "GET" ioctls (last bit set to 1). "SET" ioctls are root + * only and don't return the modified struct ifreq to the application which + * is usually a problem. - Jean II */ #define AIROIOCTL SIOCIWFIRSTPRIV #define AIROIDIFC AIROIOCTL + 1 @@ -739,20 +767,38 @@ u16 len; u8 key[16]; /* 40-bit and 104-bit keys */ } wep_key_t; + +/* Backward compatibility */ +#ifndef IW_ENCODE_NOKEY +#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ +#define IW_ENCODE_MODE (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN) +#endif /* IW_ENCODE_NOKEY */ + +#if WIRELESS_EXT > 12 +/* List of Wireless Handlers (new API) */ +static const struct iw_handler_def airo_handler_def; +#else /* WIRELESS_EXT > 12 */ +/* More Wireless Extensions backward compatibility */ +/* Part of iw_handler prototype we need (apart that we don't need it) */ +struct iw_request_info {}; +#endif /* WIRELESS_EXT > 12 */ #endif /* WIRELESS_EXT */ -static const char version[] = "airo.c 0.3 (Ben Reed & Javier Achirica)"; +static const char version[] = "airo.c 0.5 (Ben Reed & Javier Achirica)"; struct airo_info; static int get_dec_u16( char *buffer, int *start, int limit ); static void OUT4500( struct airo_info *, u16 register, u16 value ); static unsigned short IN4500( struct airo_info *, u16 register ); -static u16 setup_card(struct airo_info*, u8 *mac, ConfigRid *); +static u16 setup_card(struct airo_info*, u8 *mac); +static int enable_MAC( struct airo_info *ai, Resp *rsp ); +static void disable_MAC(struct airo_info *ai); static void enable_interrupts(struct airo_info*); static void disable_interrupts(struct airo_info*); -static u16 lock_issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp); static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp); +static u16 sendcommand(struct airo_info *ai, Cmd *pCmd); +static void completecommand(struct airo_info *ai, Resp *pRsp); static int bap_setup(struct airo_info*, u16 rid, u16 offset, int whichbap); static int aux_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen, int whichbap); @@ -766,9 +812,9 @@ *pBuf, int len); static int do_writerid( struct airo_info*, u16 rid, const void *rid_data, int len ); -static u16 transmit_allocate(struct airo_info*, int lenPayload); -static int transmit_802_3_packet(struct airo_info*, u16 TxFid, char - *pPacket, int len); +static u16 transmit_allocate(struct airo_info*, int lenPayload, int raw); +static int transmit_802_3_packet(struct airo_info*, int len, char *pPacket); +static int transmit_802_11_packet(struct airo_info*, int len, char *pPacket); static void airo_interrupt( int irq, void* dev_id, struct pt_regs *regs); @@ -792,25 +838,35 @@ int fids[MAX_FIDS]; int registered; ConfigRid config; - u16 authtype; // Used with auto_wep + int need_commit; // Need to set config char keyindex; // Used with auto wep char defindex; // Used with auto wep struct timer_list timer; struct proc_dir_entry *proc_entry; struct airo_info *next; spinlock_t aux_lock; - spinlock_t main_lock; int flags; #define FLAG_PROMISC IFF_PROMISC #define FLAG_RADIO_OFF 0x02 +#define FLAG_LOCKED 2 +#define FLAG_802_11 0x10 int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, int whichbap); - int (*header_parse)(struct sk_buff*, unsigned char *); unsigned short *flash; tdsRssiEntry *rssi; + struct semaphore sem; + struct task_struct *task; + struct tq_struct promisc_task; + struct { + struct sk_buff *skb; + int fid; + struct tq_struct task; + } xmit, xmit11; + struct net_device *wifidev; #ifdef WIRELESS_EXT - int need_commit; // Need to set config struct iw_statistics wstats; // wireless stats + unsigned long scan_timestamp; /* Time started to scan */ + struct tq_struct event_task; #ifdef WIRELESS_SPY int spy_number; u_char spy_address[IW_MAX_SPY][6]; @@ -838,13 +894,17 @@ if (first == 1) { memset(&cmd, 0, sizeof(cmd)); cmd.cmd=CMD_LISTBSS; - lock_issuecommand(ai, &cmd, &rsp); + if (down_interruptible(&ai->sem)) + return -ERESTARTSYS; + issuecommand(ai, &cmd, &rsp); + up(&ai->sem); /* Let the command take effect */ set_current_state (TASK_INTERRUPTIBLE); + ai->task = current; schedule_timeout (3*HZ); + ai->task = NULL; } - rc = PC4500_readrid(ai, - first ? RID_BSSLISTFIRST : RID_BSSLISTNEXT, + rc = PC4500_readrid(ai, first ? RID_BSSLISTFIRST : RID_BSSLISTNEXT, list, sizeof(*list)); list->len = le16_to_cpu(list->len); @@ -876,10 +936,10 @@ wkr.len = cpu_to_le16(wkr.len); wkr.kindex = cpu_to_le16(wkr.kindex); wkr.klen = cpu_to_le16(wkr.klen); - rc = do_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr)); + rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr)); if (rc!=SUCCESS) printk(KERN_ERR "airo: WEP_TEMP set %x\n", rc); if (perm) { - rc = do_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr)); + rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr)); if (rc!=SUCCESS) { printk(KERN_ERR "airo: WEP_PERM set %x\n", rc); } @@ -906,29 +966,56 @@ for(i = 0; i < 3; i++) { ssidr.ssids[i].len = cpu_to_le16(ssidr.ssids[i].len); } - rc = do_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr)); + rc = PC4500_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr)); return rc; } -static int readConfigRid(struct airo_info*ai, ConfigRid *cfgr) { - int rc = PC4500_readrid(ai, RID_ACTUALCONFIG, cfgr, sizeof(*cfgr)); +static int readConfigRid(struct airo_info*ai) { + int rc; u16 *s; + ConfigRid cfg; + + if (ai->config.len) + return SUCCESS; + + rc = PC4500_readrid(ai, RID_ACTUALCONFIG, &cfg, sizeof(cfg)); + if (rc != SUCCESS) + return rc; - for(s = &cfgr->len; s <= &cfgr->rtsThres; s++) *s = le16_to_cpu(*s); + for(s = &cfg.len; s <= &cfg.rtsThres; s++) *s = le16_to_cpu(*s); - for(s = &cfgr->shortRetryLimit; s <= &cfgr->radioType; s++) + for(s = &cfg.shortRetryLimit; s <= &cfg.radioType; s++) *s = le16_to_cpu(*s); - for(s = &cfgr->txPower; s <= &cfgr->radioSpecific; s++) + for(s = &cfg.txPower; s <= &cfg.radioSpecific; s++) *s = le16_to_cpu(*s); - for(s = &cfgr->arlThreshold; s <= &cfgr->autoWake; s++) + for(s = &cfg.arlThreshold; s <= &cfg.autoWake; s++) *s = le16_to_cpu(*s); - return rc; + ai->config = cfg; + return SUCCESS; } -static int writeConfigRid(struct airo_info*ai, ConfigRid *pcfgr) { +static inline void checkThrottle(struct airo_info *ai) { + int i; +/* Old hardware had a limit on encryption speed */ + if (ai->config.authType != AUTH_OPEN && maxencrypt) { + for(i=0; i<8; i++) { + if (ai->config.rates[i] > maxencrypt) { + ai->config.rates[i] = 0; + } + } + } +} +static int writeConfigRid(struct airo_info*ai) { u16 *s; - ConfigRid cfgr = *pcfgr; + ConfigRid cfgr; + + if (!ai->need_commit) + return SUCCESS; + + ai->need_commit = 0; + checkThrottle(ai); + cfgr = ai->config; for(s = &cfgr.len; s <= &cfgr.rtsThres; s++) *s = cpu_to_le16(*s); @@ -941,7 +1028,7 @@ for(s = &cfgr.arlThreshold; s <= &cfgr.autoWake; s++) *s = cpu_to_le16(*s); - return do_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr)); + return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr)); } static int readStatusRid(struct airo_info*ai, StatusRid *statr) { int rc = PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr)); @@ -963,7 +1050,7 @@ static int writeAPListRid(struct airo_info*ai, APListRid *aplr) { int rc; aplr->len = cpu_to_le16(aplr->len); - rc = do_writerid(ai, RID_APLIST, aplr, sizeof(*aplr)); + rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr)); return rc; } static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr) { @@ -990,18 +1077,110 @@ static int airo_open(struct net_device *dev) { struct airo_info *info = dev->priv; - enable_interrupts(info); + /* Make sure the card is configured. + * Wireless Extensions may postpone config changes until the card + * is open (to pipeline changes and speed-up card setup). If + * those changes are not yet commited, do it now - Jean II */ + if(info->need_commit) { + Resp rsp; + disable_MAC(info); + writeConfigRid(info); + enable_MAC(info, &rsp); + } + + if (info->wifidev != dev) + enable_interrupts(info); netif_start_queue(dev); return 0; } +static void get_tx_error(struct airo_info *ai, u32 fid) +{ + u16 status; + + if (bap_setup(ai, ai->fids[fid] & 0xffff, 4, BAP0) == SUCCESS) { + bap_read(ai, &status, 2, BAP0); + if (le16_to_cpu(status) & 2) /* Too many retries */ + ai->stats.tx_aborted_errors++; + if (le16_to_cpu(status) & 4) /* Transmit lifetime exceeded */ + ai->stats.tx_heartbeat_errors++; + if (le16_to_cpu(status) & 8) /* Aid fail */ + { } + if (le16_to_cpu(status) & 0x10) /* MAC disabled */ + ai->stats.tx_carrier_errors++; + if (le16_to_cpu(status) & 0x20) /* Association lost */ + { } +#if WIRELESS_EXT > 13 + /* We produce a TXDROP event only for retry or lifetime + * exceeded, because that's the only status that really mean + * that this particular node went away. + * Other errors means that *we* screwed up. - Jean II */ + if ((le16_to_cpu(status) & 2) || + (le16_to_cpu(status) & 4)) { + union iwreq_data wrqu; + char junk[0x18]; + + /* Faster to skip over useless data than to do + * another bap_setup(). We are at offset 0x6 and + * need to go to 0x18 and read 6 bytes - Jean II */ + bap_read(ai, (u16 *) junk, 0x18, BAP0); + + /* Copy 802.11 dest address. + * We use the 802.11 header because the frame may + * not be 802.3 or may be mangled... + * In Ad-Hoc mode, it will be the node address. + * In managed mode, it will be most likely the AP addr + * User space will figure out how to convert it to + * whatever it needs (IP address or else). + * - Jean II */ + memcpy(wrqu.addr.sa_data, junk + 0x12, ETH_ALEN); + wrqu.addr.sa_family = ARPHRD_ETHER; + + /* Send event to user space */ + wireless_send_event(ai->dev, IWEVTXDROP, &wrqu, NULL); + } +#endif /* WIRELESS_EXT > 13 */ + } +} + +static void airo_do_xmit(struct net_device *dev) { + u16 status; + int i; + struct airo_info *priv = dev->priv; + struct sk_buff *skb = priv->xmit.skb; + int fid = priv->xmit.fid; + u32 *fids = priv->fids; + + if (down_trylock(&priv->sem) != 0) { + netif_stop_queue(dev); + priv->xmit.task.routine = (void (*)(void *))airo_do_xmit; + priv->xmit.task.data = (void *)dev; + schedule_task(&priv->xmit.task); + return; + } + status = transmit_802_3_packet (priv, fids[fid], skb->data); + up(&priv->sem); + + i = 0; + if ( status == SUCCESS ) { + dev->trans_start = jiffies; + for (; i < MAX_FIDS / 2 && (priv->fids[i] & 0xffff0000); i++); + } else { + priv->fids[fid] &= 0xffff; + priv->stats.tx_window_errors++; + } + if (i < MAX_FIDS / 2) + netif_wake_queue(dev); + else + netif_stop_queue(dev); + dev_kfree_skb(skb); +} + static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { s16 len; - u16 status; - u32 flags; - int i,j; - struct airo_info *priv = (struct airo_info*)dev->priv; + int i; + struct airo_info *priv = dev->priv; u32 *fids = priv->fids; if ( skb == NULL ) { @@ -1010,38 +1189,88 @@ } /* Find a vacant FID */ - spin_lock_irqsave(&priv->main_lock, flags); - for( j = 0, i = -1; j < MAX_FIDS; j++ ) { - if ( !( fids[j] & 0xffff0000 ) ) { - if ( i == -1 ) i = j; - else break; - } - } - if ( j == MAX_FIDS ) netif_stop_queue(dev); - if ( i == -1 ) { + for( i = 0; i < MAX_FIDS / 2 && (fids[i] & 0xffff0000); i++ ); + + if ( i == MAX_FIDS / 2 ) { priv->stats.tx_fifo_errors++; - goto tx_done; + dev_kfree_skb(skb); + } else { + /* check min length*/ + len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + /* Mark fid as used & save length for later */ + fids[i] |= (len << 16); + priv->xmit.skb = skb; + priv->xmit.fid = i; + airo_do_xmit(dev); } + return 0; +} - len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; /* check min length*/ - status = transmit_802_3_packet( priv, fids[i], skb->data, len ); +static void airo_do_xmit11(struct net_device *dev) { + u16 status; + int i; + struct airo_info *priv = dev->priv; + struct sk_buff *skb = priv->xmit11.skb; + int fid = priv->xmit11.fid; + u32 *fids = priv->fids; + + if (down_trylock(&priv->sem) != 0) { + netif_stop_queue(dev); + priv->xmit11.task.routine = (void (*)(void *))airo_do_xmit11; + priv->xmit11.task.data = (void *)dev; + schedule_task(&priv->xmit11.task); + return; + } + status = transmit_802_11_packet (priv, fids[fid], skb->data); + up(&priv->sem); + i = MAX_FIDS / 2; if ( status == SUCCESS ) { - /* Mark fid as used & save length for later */ - fids[i] |= (len << 16); dev->trans_start = jiffies; + for (; i < MAX_FIDS && (priv->fids[i] & 0xffff0000); i++); } else { + priv->fids[fid] &= 0xffff; priv->stats.tx_window_errors++; } - tx_done: - spin_unlock_irqrestore(&priv->main_lock, flags); + if (i < MAX_FIDS) + netif_wake_queue(dev); + else + netif_stop_queue(dev); dev_kfree_skb(skb); +} + +static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { + s16 len; + int i; + struct airo_info *priv = dev->priv; + u32 *fids = priv->fids; + + if ( skb == NULL ) { + printk( KERN_ERR "airo: skb == NULL!!!\n" ); + return 0; + } + + /* Find a vacant FID */ + for( i = MAX_FIDS / 2; i < MAX_FIDS && (fids[i] & 0xffff0000); i++ ); + + if ( i == MAX_FIDS ) { + priv->stats.tx_fifo_errors++; + dev_kfree_skb(skb); + } else { + /* check min length*/ + len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + /* Mark fid as used & save length for later */ + fids[i] |= (len << 16); + priv->xmit11.skb = skb; + priv->xmit11.fid = i; + airo_do_xmit11(dev); + } return 0; } struct net_device_stats *airo_get_stats(struct net_device *dev) { - struct airo_info *local = (struct airo_info*) dev->priv; + struct airo_info *local = dev->priv; StatsRid stats_rid; u32 *vals = stats_rid.vals; @@ -1063,27 +1292,44 @@ local->stats.rx_frame_errors = vals[2]; local->stats.rx_fifo_errors = vals[0]; - return (&local->stats); + return &local->stats; } -static int enable_MAC( struct airo_info *ai, Resp *rsp ); -static void disable_MAC(struct airo_info *ai); +static void airo_end_promisc(struct airo_info *ai) { + Resp rsp; -static void airo_set_multicast_list(struct net_device *dev) { - struct airo_info *ai = (struct airo_info*)dev->priv; + if ((IN4500(ai, EVSTAT) & EV_CMD) != 0) { + completecommand(ai, &rsp); + up(&ai->sem); + } else { + ai->promisc_task.routine = (void (*)(void *))airo_end_promisc; + ai->promisc_task.data = (void *)ai; + schedule_task(&ai->promisc_task); + } +} + +static void airo_set_promisc(struct airo_info *ai) { Cmd cmd; - Resp rsp; - /* For some reason this command takes a lot of time (~20 ms) and it's - * run in an interrupt handler, so we'd better be sure we needed it - * before executing it. - */ - if ((dev->flags ^ ai->flags) & IFF_PROMISC) { + if (down_trylock(&ai->sem) == 0) { memset(&cmd, 0, sizeof(cmd)); cmd.cmd=CMD_SETMODE; - cmd.parm0=(dev->flags&IFF_PROMISC) ? PROMISC : NOPROMISC; - lock_issuecommand(ai, &cmd, &rsp); - ai->flags^=IFF_PROMISC; + cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC; + sendcommand(ai, &cmd); + airo_end_promisc(ai); + } else { + ai->promisc_task.routine = (void (*)(void *))airo_set_promisc; + ai->promisc_task.data = (void *)ai; + schedule_task(&ai->promisc_task); + } +} + +static void airo_set_multicast_list(struct net_device *dev) { + struct airo_info *ai = dev->priv; + + if ((dev->flags ^ ai->flags) & IFF_PROMISC) { + ai->flags ^= IFF_PROMISC; + airo_set_promisc(ai); } if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) { @@ -1093,14 +1339,18 @@ static int airo_set_mac_address(struct net_device *dev, void *p) { - struct airo_info *ai = (struct airo_info*)dev->priv; + struct airo_info *ai = dev->priv; struct sockaddr *addr = p; - ConfigRid cfg; + Resp rsp; - readConfigRid (ai, &cfg); - memcpy (cfg.macAddr, addr->sa_data, dev->addr_len); - writeConfigRid (ai, &cfg); - memcpy (dev->dev_addr, addr->sa_data, dev->addr_len); + memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len); + ai->need_commit = 1; + disable_MAC(ai); + writeConfigRid (ai); + enable_MAC(ai, &rsp); + memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len); + if (ai->wifidev) + memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len); return 0; } @@ -1114,10 +1364,12 @@ static int airo_close(struct net_device *dev) { - struct airo_info *ai = (struct airo_info*)dev->priv; + struct airo_info *ai = dev->priv; netif_stop_queue(dev); - disable_interrupts( ai ); + + if (ai->wifidev != dev) + disable_interrupts( ai ); return 0; } @@ -1125,7 +1377,8 @@ void stop_airo_card( struct net_device *dev, int freeres ) { - struct airo_info *ai = (struct airo_info*)dev->priv; + struct airo_info *ai = dev->priv; + flush_scheduled_tasks(); if (ai->flash) kfree(ai->flash); if (ai->rssi) @@ -1133,6 +1386,11 @@ takedown_proc_entry( dev, ai ); if (ai->registered) { unregister_netdev( dev ); + if (ai->wifidev) { + unregister_netdev(ai->wifidev); + kfree(ai->wifidev); + ai->wifidev = 0; + } ai->registered = 0; } disable_interrupts(ai); @@ -1150,6 +1408,69 @@ static int add_airo_dev( struct net_device *dev ); +int wll_header_parse(struct sk_buff *skb, unsigned char *haddr) +{ + memcpy(haddr, skb->mac.raw + 10, ETH_ALEN); + return ETH_ALEN; +} + +static void wifi_setup(struct net_device *dev, struct net_device *ethdev) +{ + struct airo_info *ai = ethdev->priv; + dev->priv = ai; + dev->hard_header = 0; + dev->rebuild_header = 0; + dev->hard_header_cache = 0; + dev->header_cache_update= 0; + + dev->hard_header_parse = wll_header_parse; + dev->hard_start_xmit = &airo_start_xmit11; + dev->get_stats = &airo_get_stats; + dev->set_mac_address = &airo_set_mac_address; + dev->do_ioctl = &airo_ioctl; +#ifdef WIRELESS_EXT + dev->get_wireless_stats = airo_get_wireless_stats; +#if WIRELESS_EXT > 12 + dev->wireless_handlers = (struct iw_handler_def *)&airo_handler_def; +#endif /* WIRELESS_EXT > 12 */ +#endif /* WIRELESS_EXT */ + dev->change_mtu = &airo_change_mtu; + dev->open = &airo_open; + dev->stop = &airo_close; + dev->irq = ethdev->irq; + dev->base_addr = ethdev->base_addr; + + dev->type = ARPHRD_IEEE80211; + dev->hard_header_len = ETH_HLEN; + dev->mtu = 2312; + dev->addr_len = ETH_ALEN; + memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len); + dev->tx_queue_len = 100; + + memset(dev->broadcast,0xFF, ETH_ALEN); + + dev->flags = IFF_BROADCAST|IFF_MULTICAST; +} + +static struct net_device *init_wifidev(struct airo_info *ai, + struct net_device *ethdev) +{ + int err; + struct net_device *dev = (struct net_device*)kmalloc(sizeof *dev,GFP_KERNEL); + if (!dev) return 0; + memset(dev, 0, sizeof(*dev)); + + strcpy(dev->name, "wifi%d"); + dev->priv = ai; + wifi_setup(dev, ethdev); + err = register_netdev(dev); + if (err<0) { + kfree(dev); + return 0; + } + return dev; +} + struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia ) { struct net_device *dev; @@ -1168,11 +1489,13 @@ } ai = dev->priv; + ai->wifidev = 0; ai->registered = 0; ai->dev = dev; ai->aux_lock = SPIN_LOCK_UNLOCKED; - ai->main_lock = SPIN_LOCK_UNLOCKED; - ai->header_parse = dev->hard_header_parse; + sema_init(&ai->sem, 1); + ai->need_commit = 0; + ai->config.len = 0; rc = add_airo_dev( dev ); if (rc) goto err_out_free; @@ -1185,6 +1508,9 @@ dev->do_ioctl = &airo_ioctl; #ifdef WIRELESS_EXT dev->get_wireless_stats = airo_get_wireless_stats; +#if WIRELESS_EXT > 12 + dev->wireless_handlers = (struct iw_handler_def *)&airo_handler_def; +#endif /* WIRELESS_EXT > 12 */ #endif /* WIRELESS_EXT */ dev->change_mtu = &airo_change_mtu; dev->open = &airo_open; @@ -1204,15 +1530,17 @@ } } - if ( setup_card( ai, dev->dev_addr, &ai->config) != SUCCESS ) { + if (probe && setup_card( ai, dev->dev_addr ) != SUCCESS ) { printk( KERN_ERR "airo: MAC could not be enabled\n" ); rc = -EIO; goto err_out_res; - } + } else + ai->bap_read = fast_bap_read; rc = register_netdev(dev); if (rc) goto err_out_res; + ai->wifidev = init_wifidev(ai, dev); ai->registered = 1; printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", @@ -1221,8 +1549,9 @@ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] ); /* Allocate the transmit buffers */ - for( i = 0; i < MAX_FIDS; i++ ) - ai->fids[i] = transmit_allocate( ai, 2312 ); + if (probe) + for( i = 0; i < MAX_FIDS; i++ ) + ai->fids[i] = transmit_allocate(ai,2312,i>=MAX_FIDS/2); setup_proc_entry( dev, dev->priv ); /* XXX check for failure */ netif_start_queue(dev); @@ -1255,9 +1584,8 @@ int reset_airo_card( struct net_device *dev ) { int i; - struct airo_info *ai = (struct airo_info*)dev->priv; + struct airo_info *ai = dev->priv; - disable_MAC(ai); waitbusy (ai); OUT4500(ai,COMMAND,CMD_SOFTRESET); set_current_state (TASK_UNINTERRUPTIBLE); @@ -1265,7 +1593,7 @@ waitbusy (ai); set_current_state (TASK_UNINTERRUPTIBLE); schedule_timeout (HZ/5); - if ( setup_card(ai, dev->dev_addr, &(ai)->config) != SUCCESS ) { + if ( setup_card(ai, dev->dev_addr ) != SUCCESS ) { printk( KERN_ERR "airo: MAC could not be enabled\n" ); return -1; } else { @@ -1280,7 +1608,7 @@ ); /* Allocate the transmit buffers */ for( i = 0; i < MAX_FIDS; i++ ) - ai->fids[i] = transmit_allocate( ai, 2312 ); + ai->fids[i] = transmit_allocate(ai,2312,i>=MAX_FIDS/2); } enable_interrupts( ai ); netif_wake_queue(dev); @@ -1289,17 +1617,37 @@ EXPORT_SYMBOL(reset_airo_card); -static int wll_header_parse(struct sk_buff *skb, unsigned char *haddr) -{ - memcpy(haddr, skb->mac.raw + 10, ETH_ALEN); - return ETH_ALEN; +#if WIRELESS_EXT > 13 +static void airo_send_event(struct net_device *dev) { + struct airo_info *ai = dev->priv; + union iwreq_data wrqu; + StatusRid status_rid; + + if (down_trylock(&ai->sem) == 0) { + __set_bit(FLAG_LOCKED, &ai->flags); + PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid)); + clear_bit(FLAG_LOCKED, &ai->flags); + up(&ai->sem); + wrqu.data.length = 0; + wrqu.data.flags = 0; + memcpy(wrqu.ap_addr.sa_data, status_rid.bssid[0], ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + + /* Send event to user space */ + wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); + } else { + ai->event_task.routine = (void (*)(void *))airo_send_event; + ai->event_task.data = (void *)dev; + schedule_task(&ai->event_task); + } } +#endif static void airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *)dev_id; u16 status; u16 fid; - struct airo_info *apriv = (struct airo_info *)dev->priv; + struct airo_info *apriv = dev->priv; u16 savedInterrupts = 0; if (!netif_device_present(dev)) @@ -1307,7 +1655,7 @@ for (;;) { status = IN4500( apriv, EVSTAT ); - if ( !status || status == 0xffff ) break; + if ( !(status & STATUS_INTS) || status == 0xffff ) break; if ( status & EV_AWAKE ) { OUT4500( apriv, EVACK, EV_AWAKE ); @@ -1320,6 +1668,9 @@ } if ( status & EV_LINK ) { +#if WIRELESS_EXT > 13 + union iwreq_data wrqu; +#endif /* WIRELESS_EXT > 13 */ /* The link status has changed, if you want to put a monitor hook in, do it here. (Remember that interrupts are still disabled!) @@ -1360,30 +1711,72 @@ apriv->timer.expires = RUN_AT(HZ*3); add_timer(&apriv->timer); } + } else { + struct task_struct *task = apriv->task; + if (task) + wake_up_process (task); + } +#if WIRELESS_EXT > 13 + /* Question : is ASSOCIATED the only status + * that is valid ? We want to catch handover + * and reassociations as valid status + * Jean II */ + if(newStatus == ASSOCIATED) { + if (apriv->scan_timestamp) { + /* Send an empty event to user space. + * We don't send the received data on + * the event because it would require + * us to do complex transcoding, and + * we want to minimise the work done in + * the irq handler. Use a request to + * extract the data - Jean II */ + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); + apriv->scan_timestamp = 0; + } + airo_send_event(dev); + } else { + memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + + /* Send event to user space */ + wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL); } +#endif /* WIRELESS_EXT > 13 */ } /* Check to see if there is something to receive */ if ( status & EV_RX ) { struct sk_buff *skb = NULL; u16 fc, len, hdrlen = 0; +#pragma pack(1) struct { u16 status, len; u8 rssi[2]; + u8 rate; + u8 freq; + u16 tmp[4]; } hdr; +#pragma pack() + u16 gap; + u16 tmpbuf[4]; + u16 *buffer; fid = IN4500( apriv, RXFID ); /* Get the packet length */ - if (dev->type == ARPHRD_IEEE80211) { + if (apriv->flags & FLAG_802_11) { bap_setup (apriv, fid, 4, BAP0); bap_read (apriv, (u16*)&hdr, sizeof(hdr), BAP0); /* Bad CRC. Ignore packet */ if (le16_to_cpu(hdr.status) & 2) hdr.len = 0; + if (apriv->wifidev == NULL) + hdr.len = 0; } else { - bap_setup (apriv, fid, 6, BAP0); - bap_read (apriv, (u16*)&hdr.len, 4, BAP0); + bap_setup (apriv, fid, 0x36, BAP0); + bap_read (apriv, (u16*)&hdr.len, 2, BAP0); } len = le16_to_cpu(hdr.len); @@ -1392,13 +1785,24 @@ len = 0; } if (len) { - if (dev->type == ARPHRD_IEEE80211) { - bap_setup (apriv, fid, 0x14, BAP0); + if (apriv->flags & FLAG_802_11) { bap_read (apriv, (u16*)&fc, sizeof(fc), BAP0); - if ((le16_to_cpu(fc) & 0x300) == 0x300) - hdrlen = 30; - else - hdrlen = 24; + fc = le16_to_cpu(fc); + switch (fc & 0xc) { + case 4: + if ((fc & 0xe0) == 0xc0) + hdrlen = 10; + else + hdrlen = 16; + break; + case 8: + if ((fc&0x300)==0x300){ + hdrlen = 30; + break; + } + default: + hdrlen = 24; + } } else hdrlen = 12; @@ -1409,10 +1813,8 @@ } } if (len) { - u16 *buffer; buffer = (u16*)skb_put (skb, len + hdrlen); - if (dev->type == ARPHRD_IEEE80211) { - u16 gap, tmpbuf[4]; + if (apriv->flags & FLAG_802_11) { buffer[0] = fc; bap_read (apriv, buffer + 1, hdrlen - 2, BAP0); if (hdrlen == 24) @@ -1420,12 +1822,16 @@ bap_read (apriv, &gap, sizeof(gap), BAP0); gap = le16_to_cpu(gap); - if (gap && gap <= 8) - bap_read (apriv, tmpbuf, gap, BAP0); + if (gap) { + if (gap <= 8) + bap_read (apriv, tmpbuf, gap, BAP0); + else + printk(KERN_ERR "airo: gaplen too big. Problems will follow...\n"); + } + bap_read (apriv, buffer + hdrlen/2, len, BAP0); } else { - bap_setup (apriv, fid, 0x38, BAP0); bap_read (apriv, buffer,len + hdrlen,BAP0); } OUT4500( apriv, EVACK, EV_RX); @@ -1434,11 +1840,15 @@ int i; char *sa; - sa = (char*)buffer + ((dev->type == ARPHRD_IEEE80211) ? 10 : 6); + sa = (char*)buffer + ((apriv->flags & FLAG_802_11) ? 10 : 6); for (i=0; ispy_number; i++) if (!memcmp(sa,apriv->spy_address[i],6)) { + if (!(apriv->flags & FLAG_802_11)) { + bap_setup (apriv, fid, 8, BAP0); + bap_read (apriv, (u16*)hdr.rssi, 2, BAP0); + } apriv->spy_stat[i].qual = hdr.rssi[0]; if (apriv->rssi) apriv->spy_stat[i].level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm; @@ -1450,16 +1860,17 @@ } } #endif /* WIRELESS_SPY */ - dev->last_rx = jiffies; - skb->dev = dev; - skb->ip_summed = CHECKSUM_NONE; - if (dev->type == ARPHRD_IEEE80211) { + if (apriv->flags & FLAG_802_11) { skb->mac.raw = skb->data; - skb_pull (skb, hdrlen); skb->pkt_type = PACKET_OTHERHOST; + skb->dev = apriv->wifidev; skb->protocol = htons(ETH_P_802_2); - } else + } else { + skb->dev = dev; skb->protocol = eth_type_trans(skb,dev); + } + skb->dev->last_rx = jiffies; + skb->ip_summed = CHECKSUM_NONE; netif_rx( skb ); } else @@ -1482,27 +1893,16 @@ apriv->fids[i] &= 0xffff; } } - if (index != -1) netif_wake_queue(dev); - if ((status & EV_TXEXC) && - (bap_setup(apriv, fid, 4, BAP1) == SUCCESS)) { - - u16 status; - bap_read(apriv, &status, 2, BAP1); - if (le16_to_cpu(status) & 2) - apriv->stats.tx_aborted_errors++; - if (le16_to_cpu(status) & 4) - apriv->stats.tx_heartbeat_errors++; - if (le16_to_cpu(status) & 0x10) - apriv->stats.tx_carrier_errors++; + if (index != -1) { + netif_wake_queue(dev); + if (status & EV_TXEXC) + get_tx_error(apriv, index); } OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC)); if (index==-1) { printk( KERN_ERR "airo: Unallocated FID was used to xmit\n" ); } } - if ( status & ~STATUS_INTS ) - OUT4500( apriv, EVACK, status & ~STATUS_INTS); - if ( status & ~STATUS_INTS & ~IGNORE_INTS ) printk( KERN_WARNING "airo: Got weird status %x\n", status & ~STATUS_INTS & ~IGNORE_INTS ); @@ -1546,12 +1946,20 @@ } static int enable_MAC( struct airo_info *ai, Resp *rsp ) { + int rc; Cmd cmd; if (ai->flags&FLAG_RADIO_OFF) return SUCCESS; memset(&cmd, 0, sizeof(cmd)); cmd.cmd = MAC_ENABLE; - return lock_issuecommand(ai, &cmd, rsp); + if (test_bit(FLAG_LOCKED, &ai->flags) != 0) + return issuecommand(ai, &cmd, rsp); + + if (down_interruptible(&ai->sem)) + return -ERESTARTSYS; + rc = issuecommand(ai, &cmd, rsp); + up(&ai->sem); + return rc; } static void disable_MAC( struct airo_info *ai ) { @@ -1560,7 +1968,15 @@ memset(&cmd, 0, sizeof(cmd)); cmd.cmd = MAC_DISABLE; // disable in case already enabled - lock_issuecommand(ai, &cmd, &rsp); + if (test_bit(FLAG_LOCKED, &ai->flags) != 0) { + issuecommand(ai, &cmd, &rsp); + return; + } + + if (down_interruptible(&ai->sem)) + return; + issuecommand(ai, &cmd, &rsp); + up(&ai->sem); } static void enable_interrupts( struct airo_info *ai ) { @@ -1577,12 +1993,10 @@ OUT4500( ai, EVINTEN, 0 ); } -static u16 setup_card(struct airo_info *ai, u8 *mac, - ConfigRid *config) +static u16 setup_card(struct airo_info *ai, u8 *mac) { Cmd cmd; Resp rsp; - ConfigRid cfg; int status; int i; SsidRid mySsid; @@ -1599,18 +2013,23 @@ /* The NOP is the first step in getting the card going */ cmd.cmd = NOP; cmd.parm0 = cmd.parm1 = cmd.parm2 = 0; - if ( lock_issuecommand( ai, &cmd, &rsp ) != SUCCESS ) { + if (down_interruptible(&ai->sem)) + return ERROR; + if ( issuecommand( ai, &cmd, &rsp ) != SUCCESS ) { + up(&ai->sem); return ERROR; } memset(&cmd, 0, sizeof(cmd)); cmd.cmd = MAC_DISABLE; // disable in case already enabled - if ( lock_issuecommand( ai, &cmd, &rsp ) != SUCCESS ) { + if ( issuecommand( ai, &cmd, &rsp ) != SUCCESS ) { + up(&ai->sem); return ERROR; } // Let's figure out if we need to use the AUX port cmd.cmd = CMD_ENABLEAUX; - if (lock_issuecommand(ai, &cmd, &rsp) != SUCCESS) { + if (issuecommand(ai, &cmd, &rsp) != SUCCESS) { + up(&ai->sem); printk(KERN_ERR "airo: Error checking for AUX port\n"); return ERROR; } @@ -1621,13 +2040,12 @@ ai->bap_read = aux_bap_read; printk(KERN_DEBUG "airo: Doing AUX bap_reads\n"); } - if ( config->len ) { - cfg = *config; - } else { + up(&ai->sem); + if (ai->config.len == 0) { tdsRssiRid rssi_rid; // general configuration (read/modify/write) - status = readConfigRid(ai, &cfg); + status = readConfigRid(ai); if ( status != SUCCESS ) return ERROR; status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid)); @@ -1643,60 +2061,63 @@ } status = readCapabilityRid(ai, &cap_rid); if ((status == SUCCESS) && (cap_rid.softCap & 8)) - cfg.rmode |= RXMODE_NORMALIZED_RSSI; + ai->config.rmode |= RXMODE_NORMALIZED_RSSI; else printk(KERN_WARNING "airo: unknown received signal level scale\n"); } - cfg.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS; + ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS; /* Save off the MAC */ for( i = 0; i < 6; i++ ) { - mac[i] = cfg.macAddr[i]; + mac[i] = ai->config.macAddr[i]; } /* Check to see if there are any insmod configured rates to add */ if ( rates ) { int i = 0; - if ( rates[0] ) memset(cfg.rates,0,sizeof(cfg.rates)); + if ( rates[0] ) memset(ai->config.rates,0,sizeof(ai->config.rates)); for( i = 0; i < 8 && rates[i]; i++ ) { - cfg.rates[i] = rates[i]; + ai->config.rates[i] = rates[i]; } } if ( basic_rate > 0 ) { int i; for( i = 0; i < 8; i++ ) { - if ( cfg.rates[i] == basic_rate || - !cfg.rates ) { - cfg.rates[i] = basic_rate | 0x80; + if ( ai->config.rates[i] == basic_rate || + !ai->config.rates ) { + ai->config.rates[i] = basic_rate | 0x80; break; } } } - cfg.authType = ai->authtype; - *config = cfg; + if (auto_wep) + ai->config.authType = AUTH_SHAREDKEY; + ai->need_commit = 1; } /* Setup the SSIDs if present */ if ( ssids[0] ) { - int i = 0; + int i; for( i = 0; i < 3 && ssids[i]; i++ ) { mySsid.ssids[i].len = strlen(ssids[i]); if ( mySsid.ssids[i].len > 32 ) mySsid.ssids[i].len = 32; memcpy(mySsid.ssids[i].ssid, ssids[i], mySsid.ssids[i].len); - mySsid.ssids[i].len = mySsid.ssids[i].len; } } - status = writeConfigRid(ai, &cfg); + status = writeConfigRid(ai); if ( status != SUCCESS ) return ERROR; /* Set up the SSID list */ status = writeSsidRid(ai, &mySsid); if ( status != SUCCESS ) return ERROR; + status = enable_MAC(ai, &rsp); + if ( status != SUCCESS ) return ERROR; + /* Grab the initial wep key, we gotta save it for auto_wep */ rc = readWepKeyRid(ai, &wkr, 1); if (rc == SUCCESS) do { @@ -1714,36 +2135,49 @@ return SUCCESS; } -static u16 lock_issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { - int rc; - long flags; +static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { + // Im really paranoid about letting it run forever! + int max_tries = 600000; - spin_lock_irqsave(&ai->main_lock, flags); - rc = issuecommand(ai, pCmd, pRsp); - spin_unlock_irqrestore(&ai->main_lock, flags); - return rc; + if (sendcommand(ai, pCmd) == (u16)ERROR) + return ERROR; + + while (max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0) { + if (!in_interrupt() && (max_tries & 255) == 0) + schedule(); + } + if ( max_tries == -1 ) { + printk( KERN_ERR + "airo: Max tries exceeded waiting for command\n" ); + return ERROR; + } + completecommand(ai, pRsp); + return SUCCESS; } -static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { +static u16 sendcommand(struct airo_info *ai, Cmd *pCmd) { // Im really paranoid about letting it run forever! int max_tries = 600000; + u16 cmd; OUT4500(ai, PARAM0, pCmd->parm0); OUT4500(ai, PARAM1, pCmd->parm1); OUT4500(ai, PARAM2, pCmd->parm2); OUT4500(ai, COMMAND, pCmd->cmd); - while ( max_tries-- && - (IN4500(ai, EVSTAT) & EV_CMD) == 0) { - if ( IN4500(ai, COMMAND) == pCmd->cmd) { - // PC4500 didn't notice command, try again - OUT4500(ai, COMMAND, pCmd->cmd); - } - } + while ( max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0 && + (cmd = IN4500(ai, COMMAND)) != 0 ) + if (cmd == pCmd->cmd) + // PC4500 didn't notice command, try again + OUT4500(ai, COMMAND, pCmd->cmd); if ( max_tries == -1 ) { printk( KERN_ERR "airo: Max tries exceeded when issueing command\n" ); return ERROR; } + return SUCCESS; +} + +static void completecommand(struct airo_info *ai, Resp *pRsp) { // command completed pRsp->status = IN4500(ai, STATUS); pRsp->rsp0 = IN4500(ai, RESP0); @@ -1756,7 +2190,6 @@ } // acknowledge processing the status/response OUT4500(ai, EVACK, EV_CMD); - return SUCCESS; } /* Sets up the bap to start exchange data. whichbap should @@ -1896,11 +2329,14 @@ * we must get a lock. */ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len) { - u16 status; - long flags; + u16 status, dolock = 0; int rc = SUCCESS; - spin_lock_irqsave(&ai->main_lock, flags); + if (test_bit(FLAG_LOCKED, &ai->flags) == 0) { + dolock = 1; + if (down_interruptible(&ai->sem)) + return ERROR; + } if ( (status = PC4500_accessrid(ai, rid, CMD_ACCESS)) != SUCCESS) { rc = status; goto done; @@ -1924,8 +2360,9 @@ } // read remainder of the rid rc = bap_read(ai, ((u16*)pBuf)+1, len, BAP1); - done: - spin_unlock_irqrestore(&ai->main_lock, flags); +done: + if (dolock) + up(&ai->sem); return rc; } @@ -1934,11 +2371,14 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, const void *pBuf, int len) { - u16 status; - long flags; + u16 status, dolock = 0; int rc = SUCCESS; - spin_lock_irqsave(&ai->main_lock, flags); + if (test_bit(FLAG_LOCKED, &ai->flags) == 0) { + dolock = 1; + if (down_interruptible(&ai->sem)) + return ERROR; + } // --- first access so that we can write the rid data if ( (status = PC4500_accessrid(ai, rid, CMD_ACCESS)) != 0) { rc = status; @@ -1953,24 +2393,32 @@ // ---now commit the rid data rc = PC4500_accessrid(ai, rid, 0x100|CMD_ACCESS); done: - spin_unlock_irqrestore(&ai->main_lock, flags); + if (dolock) + up(&ai->sem); return rc; } /* Allocates a FID to be used for transmitting packets. We only use one for now. */ -static u16 transmit_allocate(struct airo_info *ai, int lenPayload) +static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw) { Cmd cmd; Resp rsp; u16 txFid; u16 txControl; - long flags; cmd.cmd = CMD_ALLOCATETX; cmd.parm0 = lenPayload; - if (lock_issuecommand(ai, &cmd, &rsp) != SUCCESS) return 0; - if ( (rsp.status & 0xFF00) != 0) return 0; + if (down_interruptible(&ai->sem)) + return ERROR; + if (issuecommand(ai, &cmd, &rsp) != SUCCESS) { + txFid = 0; + goto done; + } + if ( (rsp.status & 0xFF00) != 0) { + txFid = 0; + goto done; + } /* wait for the allocate event/indication * It makes me kind of nervous that this can just sit here and spin, * but in practice it only loops like four times. */ @@ -1984,15 +2432,19 @@ * will be using the same one over and over again. */ /* We only have to setup the control once since we are not * releasing the fid. */ - txControl = cpu_to_le16(TXCTL_TXOK | TXCTL_TXEX | TXCTL_802_3 - | TXCTL_ETHERNET | TXCTL_NORELEASE); - spin_lock_irqsave(&ai->main_lock, flags); - if (bap_setup(ai, txFid, 0x0008, BAP1) != SUCCESS) { - spin_unlock_irqrestore(&ai->main_lock, flags); - return ERROR; - } - bap_write(ai, &txControl, sizeof(txControl), BAP1); - spin_unlock_irqrestore(&ai->main_lock, flags); + if (raw) + txControl = cpu_to_le16(TXCTL_TXOK | TXCTL_TXEX | TXCTL_802_11 + | TXCTL_ETHERNET | TXCTL_NORELEASE); + else + txControl = cpu_to_le16(TXCTL_TXOK | TXCTL_TXEX | TXCTL_802_3 + | TXCTL_ETHERNET | TXCTL_NORELEASE); + if (bap_setup(ai, txFid, 0x0008, BAP1) != SUCCESS) + txFid = ERROR; + else + bap_write(ai, &txControl, sizeof(txControl), BAP1); + +done: + up(&ai->sem); return txFid; } @@ -2000,12 +2452,13 @@ /* In general BAP1 is dedicated to transmiting packets. However, since we need a BAP when accessing RIDs, we also use BAP1 for that. Make sure the BAP1 spinlock is held when this is called. */ -static int transmit_802_3_packet(struct airo_info *ai, u16 txFid, - char *pPacket, int len) +static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket) { u16 payloadLen; Cmd cmd; Resp rsp; + u16 txFid = len; + len >>= 16; if (len < 12) { printk( KERN_WARNING "Short packet %d\n", len ); @@ -2029,6 +2482,65 @@ return SUCCESS; } +static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket) +{ + u16 fc, payloadLen; + Cmd cmd; + Resp rsp; + int hdrlen; + struct { + u8 addr4[6]; + u16 gaplen; + u8 gap[6]; + } gap; + u16 txFid = len; + len >>= 16; + gap.gaplen = 6; + + fc = le16_to_cpu(*(const u16*)pPacket); + switch (fc & 0xc) { + case 4: + if ((fc & 0xe0) == 0xc0) + hdrlen = 10; + else + hdrlen = 16; + break; + case 8: + if ((fc&0x300)==0x300){ + hdrlen = 30; + break; + } + default: + hdrlen = 24; + } + + if (len < hdrlen) { + printk( KERN_WARNING "Short packet %d\n", len ); + return ERROR; + } + + /* packet is 802.11 header + payload + * write the payload length and dst/src/payload */ + if (bap_setup(ai, txFid, 6, BAP1) != SUCCESS) return ERROR; + /* The 802.11 header aren't counted as part of the payload, so + * we have to subtract the header bytes off */ + payloadLen = cpu_to_le16(len-hdrlen); + bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1); + if (bap_setup(ai, txFid, 0x0014, BAP1) != SUCCESS) return ERROR; + bap_write(ai, (const u16*)pPacket, hdrlen, BAP1); + bap_write(ai, hdrlen == 30 ? + (const u16*)&gap.gaplen : (const u16*)&gap, 38 - hdrlen, BAP1); + + bap_write(ai, (const u16*)(pPacket + hdrlen), len - hdrlen, BAP1); + // issue the transmit command + memset( &cmd, 0, sizeof( cmd ) ); + cmd.cmd = CMD_TRANSMIT; + cmd.parm0 = txFid; + if (issuecommand(ai, &cmd, &rsp) != SUCCESS) return ERROR; + if ( (rsp.status & 0xFF00) != 0) return ERROR; + return SUCCESS; +} + /* * This is the proc_fs routines. It is a bit messier than I would * like! Feel free to clean it up! @@ -2288,7 +2800,7 @@ struct proc_data *data; struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; - struct airo_info *apriv = (struct airo_info *)dev->priv; + struct airo_info *apriv = dev->priv; CapabilityRid cap_rid; StatusRid status_rid; int i; @@ -2370,12 +2882,13 @@ struct proc_data *data; struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; - struct airo_info *apriv = (struct airo_info *)dev->priv; + struct airo_info *apriv = dev->priv; StatsRid stats; int i, j; int *vals = stats.vals; MOD_INC_USE_COUNT; + if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); @@ -2420,56 +2933,42 @@ return value; } -static void checkThrottle(ConfigRid *config) { - int i; -/* Old hardware had a limit on encryption speed */ - if (config->authType != AUTH_OPEN && maxencrypt) { - for(i=0; i<8; i++) { - if (config->rates[i] > maxencrypt) { - config->rates[i] = 0; - } - } - } -} - static void proc_config_on_close( struct inode *inode, struct file *file ) { struct proc_data *data = file->private_data; struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; - struct airo_info *ai = (struct airo_info*)dev->priv; - ConfigRid config; + struct airo_info *ai = dev->priv; Resp rsp; char *line; int need_reset = 0; if ( !data->writelen ) return; - disable_MAC(ai); - readConfigRid(ai, &config); + readConfigRid(ai); line = data->wbuffer; while( line[0] ) { /*** Mode processing */ if ( !strncmp( line, "Mode: ", 6 ) ) { line += 6; - config.rmode &= 0xfe00; + if ((ai->config.rmode & 0xff) >= RXMODE_RFMON) + need_reset = 1; + ai->config.rmode &= 0xfe00; + ai->flags &= ~FLAG_802_11; if ( line[0] == 'a' ) { - config.opmode = 0; + ai->config.opmode = 0; } else { - config.opmode = 1; - if ( line[0] == 'r' ) - config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER; - else if ( line[0] == 'y' ) - config.rmode |= RXMODE_RFMON_ANYBSS | RXMODE_DISABLE_802_3_HEADER; - } - if (config.rmode & RXMODE_DISABLE_802_3_HEADER) { - dev->type = ARPHRD_IEEE80211; - dev->hard_header_parse = wll_header_parse; - } else if (dev->type == ARPHRD_IEEE80211) { - dev->type = ARPHRD_ETHER; - dev->hard_header_parse = ai->header_parse; - need_reset = 1; + ai->config.opmode = 1; + if ( line[0] == 'r' ) { + ai->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER; + ai->flags |= FLAG_802_11; + } else if ( line[0] == 'y' ) { + ai->config.rmode |= RXMODE_RFMON_ANYBSS | RXMODE_DISABLE_802_3_HEADER; + ai->flags |= FLAG_802_11; + } else if ( line[0] == 'l' ) + ai->config.rmode |= RXMODE_LANMON; } + ai->need_commit = 1; } /*** Radio status */ @@ -2486,22 +2985,26 @@ int j; line += 10; - memset( config.nodeName, 0, 16 ); + memset( ai->config.nodeName, 0, 16 ); /* Do the name, assume a space between the mode and node name */ for( j = 0; j < 16 && line[j] != '\n'; j++ ) { - config.nodeName[j] = line[j]; + ai->config.nodeName[j] = line[j]; } + ai->need_commit = 1; } /*** PowerMode processing */ else if ( !strncmp( line, "PowerMode: ", 11 ) ) { line += 11; if ( !strncmp( line, "PSPCAM", 6 ) ) { - config.powerSaveMode = POWERSAVE_PSPCAM; + ai->config.powerSaveMode = POWERSAVE_PSPCAM; + ai->need_commit = 1; } else if ( !strncmp( line, "PSP", 3 ) ) { - config.powerSaveMode = POWERSAVE_PSP; + ai->config.powerSaveMode = POWERSAVE_PSP; + ai->need_commit = 1; } else { - config.powerSaveMode = POWERSAVE_CAM; + ai->config.powerSaveMode = POWERSAVE_CAM; + ai->need_commit = 1; } } else if ( !strncmp( line, "DataRates: ", 11 ) ) { int v, i = 0, k = 0; /* i is index into line, @@ -2509,77 +3012,91 @@ line += 11; while((v = get_dec_u16(line, &i, 3))!=-1) { - config.rates[k++] = (u8)v; + ai->config.rates[k++] = (u8)v; line += i + 1; i = 0; } + ai->need_commit = 1; } else if ( !strncmp( line, "Channel: ", 9 ) ) { int v, i = 0; line += 9; v = get_dec_u16(line, &i, i+3); - if ( v != -1 ) - config.channelSet = (u16)v; + if ( v != -1 ) { + ai->config.channelSet = (u16)v; + ai->need_commit = 1; + } } else if ( !strncmp( line, "XmitPower: ", 11 ) ) { int v, i = 0; line += 11; v = get_dec_u16(line, &i, i+3); - if ( v != -1 ) config.txPower = (u16)v; + if ( v != -1 ) { + ai->config.txPower = (u16)v; + ai->need_commit = 1; + } } else if ( !strncmp( line, "WEP: ", 5 ) ) { line += 5; switch( line[0] ) { case 's': - config.authType = (u16)AUTH_SHAREDKEY; + ai->config.authType = (u16)AUTH_SHAREDKEY; break; case 'e': - config.authType = (u16)AUTH_ENCRYPT; + ai->config.authType = (u16)AUTH_ENCRYPT; break; default: - config.authType = (u16)AUTH_OPEN; + ai->config.authType = (u16)AUTH_OPEN; break; } + ai->need_commit = 1; } else if ( !strncmp( line, "LongRetryLimit: ", 16 ) ) { int v, i = 0; line += 16; v = get_dec_u16(line, &i, 3); v = (v<0) ? 0 : ((v>255) ? 255 : v); - config.longRetryLimit = (u16)v; + ai->config.longRetryLimit = (u16)v; + ai->need_commit = 1; } else if ( !strncmp( line, "ShortRetryLimit: ", 17 ) ) { int v, i = 0; line += 17; v = get_dec_u16(line, &i, 3); v = (v<0) ? 0 : ((v>255) ? 255 : v); - config.shortRetryLimit = (u16)v; + ai->config.shortRetryLimit = (u16)v; + ai->need_commit = 1; } else if ( !strncmp( line, "RTSThreshold: ", 14 ) ) { int v, i = 0; line += 14; v = get_dec_u16(line, &i, 4); v = (v<0) ? 0 : ((v>2312) ? 2312 : v); - config.rtsThres = (u16)v; + ai->config.rtsThres = (u16)v; + ai->need_commit = 1; } else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) { int v, i = 0; line += 16; v = get_dec_u16(line, &i, 5); v = (v<0) ? 0 : v; - config.txLifetime = (u16)v; + ai->config.txLifetime = (u16)v; + ai->need_commit = 1; } else if ( !strncmp( line, "RXMSDULifetime: ", 16 ) ) { int v, i = 0; line += 16; v = get_dec_u16(line, &i, 5); v = (v<0) ? 0 : v; - config.rxLifetime = (u16)v; + ai->config.rxLifetime = (u16)v; + ai->need_commit = 1; } else if ( !strncmp( line, "TXDiversity: ", 13 ) ) { - config.txDiversity = + ai->config.txDiversity = (line[13]=='l') ? 1 : ((line[13]=='r')? 2: 3); + ai->need_commit = 1; } else if ( !strncmp( line, "RXDiversity: ", 13 ) ) { - config.rxDiversity = + ai->config.rxDiversity = (line[13]=='l') ? 1 : ((line[13]=='r')? 2: 3); + ai->need_commit = 1; } else if ( !strncmp( line, "FragThreshold: ", 15 ) ) { int v, i = 0; @@ -2587,22 +3104,23 @@ v = get_dec_u16(line, &i, 4); v = (v<256) ? 256 : ((v>2312) ? 2312 : v); v = v & 0xfffe; /* Make sure its even */ - config.fragThresh = (u16)v; + ai->config.fragThresh = (u16)v; + ai->need_commit = 1; } else if (!strncmp(line, "Modulation: ", 12)) { line += 12; switch(*line) { - case 'd': config.modulation=MOD_DEFAULT; break; - case 'c': config.modulation=MOD_CCK; break; - case 'm': config.modulation=MOD_MOK; break; + case 'd': ai->config.modulation=MOD_DEFAULT; ai->need_commit=1; break; + case 'c': ai->config.modulation=MOD_CCK; ai->need_commit=1; break; + case 'm': ai->config.modulation=MOD_MOK; ai->need_commit=1; break; default: printk( KERN_WARNING "airo: Unknown modulation\n" ); } } else if (!strncmp(line, "Preamble: ", 10)) { line += 10; switch(*line) { - case 'a': config.preamble=PREAMBLE_AUTO; break; - case 'l': config.preamble=PREAMBLE_LONG; break; - case 's': config.preamble=PREAMBLE_SHORT; break; + case 'a': ai->config.preamble=PREAMBLE_AUTO; ai->need_commit=1; break; + case 'l': ai->config.preamble=PREAMBLE_LONG; ai->need_commit=1; break; + case 's': ai->config.preamble=PREAMBLE_SHORT; ai->need_commit=1; break; default: printk(KERN_WARNING "airo: Unknown preamble\n"); } } else { @@ -2611,8 +3129,7 @@ while( line[0] && line[0] != '\n' ) line++; if ( line[0] ) line++; } - checkThrottle(&config); - ai->config = config; + disable_MAC(ai); if (need_reset) { APListRid APList_rid; SsidRid SSID_rid; @@ -2620,19 +3137,30 @@ readAPListRid(ai, &APList_rid); readSsidRid(ai, &SSID_rid); reset_airo_card(dev); + disable_MAC(ai); writeSsidRid(ai, &SSID_rid); writeAPListRid(ai, &APList_rid); } - writeConfigRid(ai, &config); + writeConfigRid(ai); enable_MAC(ai, &rsp); + if (need_reset) + airo_set_promisc(ai); +} + +static char *get_rmode(u16 mode) { + switch(mode&0xff) { + case RXMODE_RFMON: return "rfmon"; + case RXMODE_RFMON_ANYBSS: return "yna (any) bss rfmon"; + case RXMODE_LANMON: return "lanmon"; + } + return "ESS"; } static int proc_config_open( struct inode *inode, struct file *file ) { struct proc_data *data; struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; - struct airo_info *ai = (struct airo_info*)dev->priv; - ConfigRid config; + struct airo_info *ai = dev->priv; int i; MOD_INC_USE_COUNT; @@ -2654,7 +3182,7 @@ data->maxwritelen = 2048; data->on_close = proc_config_on_close; - readConfigRid(ai, &config); + readConfigRid(ai); i = sprintf( data->rbuffer, "Mode: %s\n" @@ -2664,25 +3192,25 @@ "DataRates: %d %d %d %d %d %d %d %d\n" "Channel: %d\n" "XmitPower: %d\n", - config.opmode == 0 ? "adhoc" : - config.opmode == 1 ? "ESS" : - config.opmode == 2 ? "AP" : - config.opmode == 3 ? "AP RPTR" : "Error", + ai->config.opmode == 0 ? "adhoc" : + ai->config.opmode == 1 ? get_rmode(ai->config.rmode): + ai->config.opmode == 2 ? "AP" : + ai->config.opmode == 3 ? "AP RPTR" : "Error", ai->flags&FLAG_RADIO_OFF ? "off" : "on", - config.nodeName, - config.powerSaveMode == 0 ? "CAM" : - config.powerSaveMode == 1 ? "PSP" : - config.powerSaveMode == 2 ? "PSPCAM" : "Error", - (int)config.rates[0], - (int)config.rates[1], - (int)config.rates[2], - (int)config.rates[3], - (int)config.rates[4], - (int)config.rates[5], - (int)config.rates[6], - (int)config.rates[7], - (int)config.channelSet, - (int)config.txPower + ai->config.nodeName, + ai->config.powerSaveMode == 0 ? "CAM" : + ai->config.powerSaveMode == 1 ? "PSP" : + ai->config.powerSaveMode == 2 ? "PSPCAM" : "Error", + (int)ai->config.rates[0], + (int)ai->config.rates[1], + (int)ai->config.rates[2], + (int)ai->config.rates[3], + (int)ai->config.rates[4], + (int)ai->config.rates[5], + (int)ai->config.rates[6], + (int)ai->config.rates[7], + (int)ai->config.channelSet, + (int)ai->config.txPower ); sprintf( data->rbuffer + i, "LongRetryLimit: %d\n" @@ -2696,24 +3224,24 @@ "WEP: %s\n" "Modulation: %s\n" "Preamble: %s\n", - (int)config.longRetryLimit, - (int)config.shortRetryLimit, - (int)config.rtsThres, - (int)config.txLifetime, - (int)config.rxLifetime, - config.txDiversity == 1 ? "left" : - config.txDiversity == 2 ? "right" : "both", - config.rxDiversity == 1 ? "left" : - config.rxDiversity == 2 ? "right" : "both", - (int)config.fragThresh, - config.authType == AUTH_ENCRYPT ? "encrypt" : - config.authType == AUTH_SHAREDKEY ? "shared" : "open", - config.modulation == 0 ? "default" : - config.modulation == MOD_CCK ? "cck" : - config.modulation == MOD_MOK ? "mok" : "error", - config.preamble == PREAMBLE_AUTO ? "auto" : - config.preamble == PREAMBLE_LONG ? "long" : - config.preamble == PREAMBLE_SHORT ? "short" : "error" + (int)ai->config.longRetryLimit, + (int)ai->config.shortRetryLimit, + (int)ai->config.rtsThres, + (int)ai->config.txLifetime, + (int)ai->config.rxLifetime, + ai->config.txDiversity == 1 ? "left" : + ai->config.txDiversity == 2 ? "right" : "both", + ai->config.rxDiversity == 1 ? "left" : + ai->config.rxDiversity == 2 ? "right" : "both", + (int)ai->config.fragThresh, + ai->config.authType == AUTH_ENCRYPT ? "encrypt" : + ai->config.authType == AUTH_SHAREDKEY ? "shared" : "open", + ai->config.modulation == 0 ? "default" : + ai->config.modulation == MOD_CCK ? "cck" : + ai->config.modulation == MOD_MOK ? "mok" : "error", + ai->config.preamble == PREAMBLE_AUTO ? "auto" : + ai->config.preamble == PREAMBLE_LONG ? "long" : + ai->config.preamble == PREAMBLE_SHORT ? "short" : "error" ); data->readlen = strlen( data->rbuffer ); return 0; @@ -2723,8 +3251,9 @@ struct proc_data *data = (struct proc_data *)file->private_data; struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; - struct airo_info *ai = (struct airo_info*)dev->priv; + struct airo_info *ai = dev->priv; SsidRid SSID_rid; + Resp rsp; int i; int offset = 0; @@ -2745,7 +3274,9 @@ offset < data->writelen ) offset++; offset++; } + disable_MAC(ai); writeSsidRid(ai, &SSID_rid); + enable_MAC(ai, &rsp); } inline static u8 hexVal(char c) { @@ -2759,8 +3290,9 @@ struct proc_data *data = (struct proc_data *)file->private_data; struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; - struct airo_info *ai = (struct airo_info*)dev->priv; + struct airo_info *ai = dev->priv; APListRid APList_rid; + Resp rsp; int i; if ( !data->writelen ) return; @@ -2783,7 +3315,9 @@ } } } + disable_MAC(ai); writeAPListRid(ai, &APList_rid); + enable_MAC(ai, &rsp); } /* This function wraps PC4500_writerid with a MAC disable */ @@ -2852,7 +3386,7 @@ struct proc_data *data; struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; - struct airo_info *ai = (struct airo_info*)dev->priv; + struct airo_info *ai = dev->priv; int i; char key[16]; u16 index = 0; @@ -2893,7 +3427,7 @@ struct proc_data *data; struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; - struct airo_info *ai = (struct airo_info*)dev->priv; + struct airo_info *ai = dev->priv; char *ptr; WepKeyRid wkr; u16 lastindex; @@ -2945,7 +3479,7 @@ struct proc_data *data; struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; - struct airo_info *ai = (struct airo_info*)dev->priv; + struct airo_info *ai = dev->priv; int i; char *ptr; SsidRid SSID_rid; @@ -2991,7 +3525,7 @@ struct proc_data *data; struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; - struct airo_info *ai = (struct airo_info*)dev->priv; + struct airo_info *ai = dev->priv; int i; char *ptr; APListRid APList_rid; @@ -3041,7 +3575,7 @@ struct proc_data *data; struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; - struct airo_info *ai = (struct airo_info*)dev->priv; + struct airo_info *ai = dev->priv; char *ptr; BSSListRid BSSList_rid; int rc; @@ -3070,7 +3604,10 @@ memset(&cmd, 0, sizeof(cmd)); cmd.cmd=CMD_LISTBSS; - lock_issuecommand(ai, &cmd, &rsp); + if (down_interruptible(&ai->sem)) + return -ERESTARTSYS; + issuecommand(ai, &cmd, &rsp); + up(&ai->sem); data->readlen = 0; return 0; } @@ -3128,39 +3665,46 @@ changed. */ static void timer_func( u_long data ) { struct net_device *dev = (struct net_device*)data; - struct airo_info *apriv = (struct airo_info *)dev->priv; + struct airo_info *apriv = dev->priv; u16 linkstat = IN4500(apriv, LINKSTAT); + Resp rsp; if (linkstat != 0x400 ) { /* We don't have a link so try changing the authtype */ - ConfigRid config = apriv->config; + if (down_trylock(&apriv->sem) != 0) { + apriv->timer.expires = RUN_AT(1); + add_timer(&apriv->timer); + return; + } + __set_bit(FLAG_LOCKED, &apriv->flags); - switch(apriv->authtype) { + readConfigRid(apriv); + disable_MAC(apriv); + switch(apriv->config.authType) { case AUTH_ENCRYPT: /* So drop to OPEN */ - config.authType = AUTH_OPEN; - apriv->authtype = AUTH_OPEN; + apriv->config.authType = AUTH_OPEN; break; case AUTH_SHAREDKEY: if (apriv->keyindex < auto_wep) { set_wep_key(apriv, apriv->keyindex, 0, 0, 0); - config.authType = AUTH_SHAREDKEY; - apriv->authtype = AUTH_SHAREDKEY; + apriv->config.authType = AUTH_SHAREDKEY; apriv->keyindex++; } else { /* Drop to ENCRYPT */ apriv->keyindex = 0; set_wep_key(apriv, apriv->defindex, 0, 0, 0); - config.authType = AUTH_ENCRYPT; - apriv->authtype = AUTH_ENCRYPT; + apriv->config.authType = AUTH_ENCRYPT; } break; default: /* We'll escalate to SHAREDKEY */ - config.authType = AUTH_SHAREDKEY; - apriv->authtype = AUTH_SHAREDKEY; + apriv->config.authType = AUTH_SHAREDKEY; } - checkThrottle(&config); - writeConfigRid(apriv, &config); + apriv->need_commit = 1; + writeConfigRid(apriv); + enable_MAC(apriv, &rsp); + clear_bit(FLAG_LOCKED, &apriv->flags); + up(&apriv->sem); /* Schedule check to see if the change worked */ apriv->timer.expires = RUN_AT(HZ*3); @@ -3180,7 +3724,6 @@ timer->function = timer_func; timer->data = (u_long)dev; init_timer(timer); - apriv->authtype = AUTH_SHAREDKEY; } node->dev = dev; @@ -3261,911 +3804,1725 @@ /* * Initial Wireless Extension code for Aironet driver by : * Jean Tourrilhes - HPL - 17 November 00 + * Conversion to new driver API by : + * Jean Tourrilhes - HPL - 26 March 02 + * Javier also did a good amount of work here, adding some new extensions + * and fixing my code. Let's just say that without him this code just + * would not work at all... - Jean II */ -#ifndef IW_ENCODE_NOKEY -#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ -#define IW_ENCODE_MODE (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN) -#endif /* IW_ENCODE_NOKEY */ -#endif /* WIRELESS_EXT */ +/*------------------------------------------------------------------*/ /* - * This defines the configuration part of the Wireless Extensions - * Note : irq and spinlock protection will occur in the subroutines - * - * TODO : - * o Check input value more carefully and fill correct values in range - * o Implement : POWER, SPY, APLIST - * o Optimise when adapter is closed (aggregate changes, commit later) - * o Test and shakeout the bugs (if any) - * - * Jean II - * - * Javier Achirica did a great job of merging code from the unnamed CISCO - * developer that added support for flashing the card. + * Wireless Handler : get protocol name */ -static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static int airo_get_name(struct net_device *dev, + struct iw_request_info *info, + char *cwrq, + char *extra) { - int i, rc = 0; -#ifdef WIRELESS_EXT - struct airo_info *local = (struct airo_info*) dev->priv; - struct iwreq *wrq = (struct iwreq *) rq; - ConfigRid config; /* Configuration info */ - CapabilityRid cap_rid; /* Card capability info */ - StatusRid status_rid; /* Card status info */ + strcpy(cwrq, "IEEE 802.11-DS"); + return 0; +} -#ifdef CISCO_EXT - if (cmd != SIOCGIWPRIV && cmd != AIROIOCTL && cmd != AIROIDIFC -#ifdef AIROOLDIOCTL - && cmd != AIROOLDIOCTL && cmd != AIROOLDIDIFC -#endif - ) -#endif /* CISCO_EXT */ - { - /* If the command read some stuff, we better get it out of - * the card first... */ - if(IW_IS_GET(cmd)) - readStatusRid(local, &status_rid); - if(IW_IS_GET(cmd) || (cmd == SIOCSIWRATE) || (cmd == SIOCSIWENCODE)) - readCapabilityRid(local, &cap_rid); - /* Get config in all cases, because SET will just modify it */ - readConfigRid(local, &config); +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set frequency + */ +static int airo_set_freq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *fwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + int rc = -EINPROGRESS; /* Call commit handler */ + + /* If setting by frequency, convert to a channel */ + if((fwrq->e == 1) && + (fwrq->m >= (int) 2.412e8) && + (fwrq->m <= (int) 2.487e8)) { + int f = fwrq->m / 100000; + int c = 0; + while((c < 14) && (f != frequency_list[c])) + c++; + /* Hack to fall through... */ + fwrq->e = 0; + fwrq->m = c + 1; } -#endif /* WIRELESS_EXT */ + /* Setting by channel number */ + if((fwrq->m > 1000) || (fwrq->e > 0)) + rc = -EOPNOTSUPP; + else { + int channel = fwrq->m; + /* We should do a better check than that, + * based on the card capability !!! */ + if((channel < 1) || (channel > 16)) { + printk(KERN_DEBUG "%s: New channel value of %d is invalid!\n", dev->name, fwrq->m); + rc = -EINVAL; + } else { + /* Yes ! We can set it !!! */ + local->config.channelSet = (u16)(channel - 1); + local->need_commit = 1; + } + } + return rc; +} - switch (cmd) { -#ifdef WIRELESS_EXT - // Get name - case SIOCGIWNAME: - strcpy(wrq->u.name, "IEEE 802.11-DS"); - break; +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get frequency + */ +static int airo_get_freq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *fwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + StatusRid status_rid; /* Card status info */ - // Set frequency/channel - case SIOCSIWFREQ: - /* If setting by frequency, convert to a channel */ - if((wrq->u.freq.e == 1) && - (wrq->u.freq.m >= (int) 2.412e8) && - (wrq->u.freq.m <= (int) 2.487e8)) { - int f = wrq->u.freq.m / 100000; - int c = 0; - while((c < 14) && (f != frequency_list[c])) - c++; - /* Hack to fall through... */ - wrq->u.freq.e = 0; - wrq->u.freq.m = c + 1; - } - /* Setting by channel number */ - if((wrq->u.freq.m > 1000) || (wrq->u.freq.e > 0)) - rc = -EOPNOTSUPP; - else { - int channel = wrq->u.freq.m; - /* We should do a better check than that, - * based on the card capability !!! */ - if((channel < 1) || (channel > 16)) { - printk(KERN_DEBUG "%s: New channel value of %d is invalid!\n", dev->name, wrq->u.freq.m); - rc = -EINVAL; - } else { - /* Yes ! We can set it !!! */ - config.channelSet = (u16)(channel - 1); - local->need_commit = 1; - } - } - break; + readStatusRid(local, &status_rid); - // Get frequency/channel - case SIOCGIWFREQ: + /* Will return zero in infrastructure mode */ #ifdef WEXT_USECHANNELS - wrq->u.freq.m = ((int)status_rid.channel) + 1; - wrq->u.freq.e = 0; + fwrq->m = ((int)status_rid.channel) + 1; + fwrq->e = 0; #else - { - int f = (int)status_rid.channel; - wrq->u.freq.m = frequency_list[f] * 100000; - wrq->u.freq.e = 1; - } + { + int f = (int)status_rid.channel; + fwrq->m = frequency_list[f] * 100000; + fwrq->e = 1; + } #endif - break; - // Set desired network name (ESSID) - case SIOCSIWESSID: - if (wrq->u.data.pointer) { - char essid[IW_ESSID_MAX_SIZE + 1]; - SsidRid SSID_rid; /* SSIDs */ - - /* Reload the list of current SSID */ - readSsidRid(local, &SSID_rid); - - /* Check if we asked for `any' */ - if(wrq->u.data.flags == 0) { - /* Just send an empty SSID list */ - memset(&SSID_rid, 0, sizeof(SSID_rid)); - } else { - int index = (wrq->u.data.flags & - IW_ENCODE_INDEX) - 1; + return 0; +} - /* Check the size of the string */ - if(wrq->u.data.length > IW_ESSID_MAX_SIZE+1) { - rc = -E2BIG; - break; - } - /* Check if index is valid */ - if((index < 0) || (index >= 4)) { - rc = -EINVAL; - break; - } +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set ESSID + */ +static int airo_set_essid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + Resp rsp; + SsidRid SSID_rid; /* SSIDs */ - /* Set the SSID */ - memset(essid, 0, sizeof(essid)); - if (copy_from_user(essid, - wrq->u.data.pointer, - wrq->u.data.length)) { - rc = -EFAULT; - break; - } - memcpy(SSID_rid.ssids[index].ssid, essid, - sizeof(essid) - 1); - SSID_rid.ssids[index].len = wrq->u.data.length - 1; - } - /* Write it to the card */ - writeSsidRid(local, &SSID_rid); - } - break; + /* Reload the list of current SSID */ + readSsidRid(local, &SSID_rid); - // Get current network name (ESSID) - case SIOCGIWESSID: - if (wrq->u.data.pointer) { - char essid[IW_ESSID_MAX_SIZE + 1]; - - /* Note : if wrq->u.data.flags != 0, we should - * get the relevant SSID from the SSID list... */ - - /* Get the current SSID */ - memcpy(essid, status_rid.SSID, status_rid.SSIDlen); - essid[status_rid.SSIDlen] = '\0'; - /* If none, we may want to get the one that was set */ - - /* Push it out ! */ - wrq->u.data.length = strlen(essid) + 1; - wrq->u.data.flags = 1; /* active */ - if (copy_to_user(wrq->u.data.pointer, essid, sizeof(essid))) - rc = -EFAULT; + /* Check if we asked for `any' */ + if(dwrq->flags == 0) { + /* Just send an empty SSID list */ + memset(&SSID_rid, 0, sizeof(SSID_rid)); + } else { + int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + + /* Check the size of the string */ + if(dwrq->length > IW_ESSID_MAX_SIZE+1) { + return -E2BIG ; + } + /* Check if index is valid */ + if((index < 0) || (index >= 4)) { + return -EINVAL; } - break; - case SIOCSIWAP: - if (wrq->u.ap_addr.sa_family != ARPHRD_ETHER) - rc = -EINVAL; - else { - APListRid APList_rid; + /* Set the SSID */ + memset(SSID_rid.ssids[index].ssid, 0, + sizeof(SSID_rid.ssids[index].ssid)); + memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length); + SSID_rid.ssids[index].len = dwrq->length - 1; + } + /* Write it to the card */ + disable_MAC(local); + writeSsidRid(local, &SSID_rid); + enable_MAC(local, &rsp); - memset(&APList_rid, 0, sizeof(APList_rid)); - APList_rid.len = sizeof(APList_rid); - memcpy(APList_rid.ap[0], wrq->u.ap_addr.sa_data, 6); - writeAPListRid(local, &APList_rid); - local->need_commit = 1; - } - break; + return 0; +} - // Get current Access Point (BSSID) - case SIOCGIWAP: - /* Tentative. This seems to work, wow, I'm lucky !!! */ - memcpy(wrq->u.ap_addr.sa_data, status_rid.bssid[0], 6); - wrq->u.ap_addr.sa_family = ARPHRD_ETHER; - break; +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get ESSID + */ +static int airo_get_essid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + StatusRid status_rid; /* Card status info */ - // Set desired station name - case SIOCSIWNICKN: - if (wrq->u.data.pointer) { - char name[16 + 1]; + readStatusRid(local, &status_rid); - /* Check the size of the string */ - if(wrq->u.data.length > 16 + 1) { - rc = -E2BIG; - break; - } - memset(name, 0, sizeof(name)); - if (copy_from_user(name, wrq->u.data.pointer, - wrq->u.data.length)) { - rc = -EFAULT; - break; - } - memcpy(config.nodeName, name, 16); - local->need_commit = 1; - } - break; + /* Note : if dwrq->flags != 0, we should + * get the relevant SSID from the SSID list... */ - // Get current station name - case SIOCGIWNICKN: - if (wrq->u.data.pointer) { - char name[IW_ESSID_MAX_SIZE + 1]; - - strncpy(name, config.nodeName, 16); - name[16] = '\0'; - wrq->u.data.length = strlen(name) + 1; - if (copy_to_user(wrq->u.data.pointer, name, sizeof(name))) - rc = -EFAULT; - } - break; + /* Get the current SSID */ + memcpy(extra, status_rid.SSID, status_rid.SSIDlen); + extra[status_rid.SSIDlen] = '\0'; + /* If none, we may want to get the one that was set */ + + /* Push it out ! */ + dwrq->length = status_rid.SSIDlen + 1; + dwrq->flags = 1; /* active */ - // Set the desired bit-rate - case SIOCSIWRATE: - { - /* First : get a valid bit rate value */ - u8 brate = 0; - int i; - - /* Which type of value ? */ - if((wrq->u.bitrate.value < 8) && - (wrq->u.bitrate.value >= 0)) { - /* Setting by rate index */ - /* Find value in the magic rate table */ - brate = cap_rid.supportedRates[wrq->u.bitrate.value]; - } else { - /* Setting by frequency value */ - u8 normvalue = (u8) (wrq->u.bitrate.value/500000); + return 0; +} - /* Check if rate is valid */ - for(i = 0 ; i < 8 ; i++) { - if(normvalue == cap_rid.supportedRates[i]) { - brate = normvalue; - break; - } - } - } - /* -1 designed the max rate (mostly auto mode) */ - if(wrq->u.bitrate.value == -1) { - /* Get the highest available rate */ - for(i = 0 ; i < 8 ; i++) { - if(cap_rid.supportedRates[i] == 0) - break; +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set AP address + */ +static int airo_set_wap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *awrq, + char *extra) +{ + struct airo_info *local = dev->priv; + Cmd cmd; + Resp rsp; + APListRid APList_rid; + static const unsigned char bcast[6] = { 255, 255, 255, 255, 255, 255 }; + + if (awrq->sa_family != ARPHRD_ETHER) + return -EINVAL; + else if (!memcmp(bcast, awrq->sa_data, 6)) { + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd=CMD_LOSE_SYNC; + if (down_interruptible(&local->sem)) + return -ERESTARTSYS; + issuecommand(local, &cmd, &rsp); + up(&local->sem); + } else { + memset(&APList_rid, 0, sizeof(APList_rid)); + APList_rid.len = sizeof(APList_rid); + memcpy(APList_rid.ap[0], awrq->sa_data, 6); + disable_MAC(local); + writeAPListRid(local, &APList_rid); + enable_MAC(local, &rsp); + } + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get AP address + */ +static int airo_get_wap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *awrq, + char *extra) +{ + struct airo_info *local = dev->priv; + StatusRid status_rid; /* Card status info */ + + readStatusRid(local, &status_rid); + + /* Tentative. This seems to work, wow, I'm lucky !!! */ + memcpy(awrq->sa_data, status_rid.bssid[0], 6); + awrq->sa_family = ARPHRD_ETHER; + + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set Nickname + */ +static int airo_set_nick(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + + /* Check the size of the string */ + if(dwrq->length > 16 + 1) { + return -E2BIG; + } + memset(local->config.nodeName, 0, sizeof(local->config.nodeName)); + memcpy(local->config.nodeName, extra, dwrq->length); + local->need_commit = 1; + + return -EINPROGRESS; /* Call commit handler */ +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get Nickname + */ +static int airo_get_nick(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + + strncpy(extra, local->config.nodeName, 16); + extra[16] = '\0'; + dwrq->length = strlen(extra) + 1; + + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set Bit-Rate + */ +static int airo_set_rate(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + CapabilityRid cap_rid; /* Card capability info */ + u8 brate = 0; + int i; + + /* First : get a valid bit rate value */ + readCapabilityRid(local, &cap_rid); + + /* Which type of value ? */ + if((vwrq->value < 8) && (vwrq->value >= 0)) { + /* Setting by rate index */ + /* Find value in the magic rate table */ + brate = cap_rid.supportedRates[vwrq->value]; + } else { + /* Setting by frequency value */ + u8 normvalue = (u8) (vwrq->value/500000); + + /* Check if rate is valid */ + for(i = 0 ; i < 8 ; i++) { + if(normvalue == cap_rid.supportedRates[i]) { + brate = normvalue; + break; } - if(i != 0) - brate = cap_rid.supportedRates[i - 1]; } - /* Check that it is valid */ - if(brate == 0) { - rc = -EINVAL; - break; + } + /* -1 designed the max rate (mostly auto mode) */ + if(vwrq->value == -1) { + /* Get the highest available rate */ + for(i = 0 ; i < 8 ; i++) { + if(cap_rid.supportedRates[i] == 0) + break; } + if(i != 0) + brate = cap_rid.supportedRates[i - 1]; + } + /* Check that it is valid */ + if(brate == 0) { + return -EINVAL; + } - /* Now, check if we want a fixed or auto value */ - if(wrq->u.bitrate.fixed == 0) { - /* Fill all the rates up to this max rate */ - memset(config.rates, 0, 8); - for(i = 0 ; i < 8 ; i++) { - config.rates[i] = cap_rid.supportedRates[i]; - if(config.rates[i] == brate) - break; - } - local->need_commit = 1; - } else { - /* Fixed mode */ - /* One rate, fixed */ - memset(config.rates, 0, 8); - config.rates[0] = brate; - local->need_commit = 1; + /* Now, check if we want a fixed or auto value */ + if(vwrq->fixed == 0) { + /* Fill all the rates up to this max rate */ + memset(local->config.rates, 0, 8); + for(i = 0 ; i < 8 ; i++) { + local->config.rates[i] = cap_rid.supportedRates[i]; + if(local->config.rates[i] == brate) + break; } - break; + } else { + /* Fixed mode */ + /* One rate, fixed */ + memset(local->config.rates, 0, 8); + local->config.rates[0] = brate; } + local->need_commit = 1; - // Get the current bit-rate - case SIOCGIWRATE: - { - int brate = status_rid.currentXmitRate; - wrq->u.bitrate.value = brate * 500000; - /* If more than one rate, set auto */ - wrq->u.rts.fixed = (config.rates[1] == 0); - } - break; + return -EINPROGRESS; /* Call commit handler */ +} - // Set the desired RTS threshold - case SIOCSIWRTS: - { - int rthr = wrq->u.rts.value; - if(wrq->u.rts.disabled) - rthr = 2312; - if((rthr < 0) || (rthr > 2312)) { - rc = -EINVAL; - } else { - config.rtsThres = rthr; - local->need_commit = 1; - } +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get Bit-Rate + */ +static int airo_get_rate(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + StatusRid status_rid; /* Card status info */ + + readStatusRid(local, &status_rid); + + vwrq->value = status_rid.currentXmitRate * 500000; + /* If more than one rate, set auto */ + vwrq->fixed = (local->config.rates[1] == 0); + + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set RTS threshold + */ +static int airo_set_rts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + int rthr = vwrq->value; + + if(vwrq->disabled) + rthr = 2312; + if((rthr < 0) || (rthr > 2312)) { + return -EINVAL; } - break; + local->config.rtsThres = rthr; + local->need_commit = 1; - // Get the current RTS threshold - case SIOCGIWRTS: - wrq->u.rts.value = config.rtsThres; - wrq->u.rts.disabled = (wrq->u.rts.value >= 2312); - wrq->u.rts.fixed = 1; - break; + return -EINPROGRESS; /* Call commit handler */ +} - // Set the desired fragmentation threshold - case SIOCSIWFRAG: - { - int fthr = wrq->u.frag.value; - if(wrq->u.frag.disabled) - fthr = 2312; - if((fthr < 256) || (fthr > 2312)) { - rc = -EINVAL; - } else { - fthr &= ~0x1; /* Get an even value */ - config.fragThresh = (u16)fthr; - local->need_commit = 1; - } +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get RTS threshold + */ +static int airo_get_rts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + + vwrq->value = local->config.rtsThres; + vwrq->disabled = (vwrq->value >= 2312); + vwrq->fixed = 1; + + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set Fragmentation threshold + */ +static int airo_set_frag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + int fthr = vwrq->value; + + if(vwrq->disabled) + fthr = 2312; + if((fthr < 256) || (fthr > 2312)) { + return -EINVAL; } - break; + fthr &= ~0x1; /* Get an even value - is it really needed ??? */ + local->config.fragThresh = (u16)fthr; + local->need_commit = 1; - // Get the current fragmentation threshold - case SIOCGIWFRAG: - wrq->u.frag.value = config.fragThresh; - wrq->u.frag.disabled = (wrq->u.frag.value >= 2312); - wrq->u.frag.fixed = 1; - break; + return -EINPROGRESS; /* Call commit handler */ +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get Fragmentation threshold + */ +static int airo_get_frag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + + vwrq->value = local->config.fragThresh; + vwrq->disabled = (vwrq->value >= 2312); + vwrq->fixed = 1; + + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set Mode of Operation + */ +static int airo_set_mode(struct net_device *dev, + struct iw_request_info *info, + __u32 *uwrq, + char *extra) +{ + struct airo_info *local = dev->priv; - // Set mode of operation - case SIOCSIWMODE: - switch(wrq->u.mode) { + switch(*uwrq) { case IW_MODE_ADHOC: - config.opmode = MODE_STA_IBSS; - local->need_commit = 1; + local->config.opmode = MODE_STA_IBSS; break; case IW_MODE_INFRA: - config.opmode = MODE_STA_ESS; - local->need_commit = 1; + local->config.opmode = MODE_STA_ESS; break; case IW_MODE_MASTER: - config.opmode = MODE_AP; - local->need_commit = 1; + local->config.opmode = MODE_AP; break; case IW_MODE_REPEAT: - config.opmode = MODE_AP_RPTR; - local->need_commit = 1; + local->config.opmode = MODE_AP_RPTR; break; default: - rc = -EINVAL; - } - break; + return -EINVAL; + } + local->need_commit = 1; + + return -EINPROGRESS; /* Call commit handler */ +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get Mode of Operation + */ +static int airo_get_mode(struct net_device *dev, + struct iw_request_info *info, + __u32 *uwrq, + char *extra) +{ + struct airo_info *local = dev->priv; - // Get mode of operation - case SIOCGIWMODE: - /* If not managed, assume it's ad-hoc */ - switch (config.opmode & 0xFF) { + /* If not managed, assume it's ad-hoc */ + switch (local->config.opmode & 0xFF) { case MODE_STA_ESS: - wrq->u.mode = IW_MODE_INFRA; + *uwrq = IW_MODE_INFRA; break; case MODE_AP: - wrq->u.mode = IW_MODE_MASTER; + *uwrq = IW_MODE_MASTER; break; case MODE_AP_RPTR: - wrq->u.mode = IW_MODE_REPEAT; + *uwrq = IW_MODE_REPEAT; break; default: - wrq->u.mode = IW_MODE_ADHOC; - } - break; + *uwrq = IW_MODE_ADHOC; + } - // Set WEP keys and mode - case SIOCSIWENCODE: - /* Is WEP supported ? */ - /* Older firmware doesn't support this... - if(!(cap_rid.softCap & 2)) { - rc = -EOPNOTSUPP; - break; - } */ - /* Basic checking: do we have a key to set ? */ - if (wrq->u.encoding.pointer != (caddr_t) 0) { - wep_key_t key; - int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1; - int current_index = get_wep_key(local, 0xffff); - /* Check the size of the key */ - if (wrq->u.encoding.length > MAX_KEY_SIZE) { - rc = -EINVAL; - break; - } - /* Check the index (none -> use current) */ - if ((index < 0) || (index>=(cap_rid.softCap&0x80)?4:1)) - index = current_index; - /* Set the length */ - if (wrq->u.encoding.length > MIN_KEY_SIZE) - key.len = MAX_KEY_SIZE; - else - if (wrq->u.encoding.length > 0) - key.len = MIN_KEY_SIZE; - else - /* Disable the key */ - key.len = 0; - /* Check if the key is not marked as invalid */ - if(!(wrq->u.encoding.flags & IW_ENCODE_NOKEY)) { - /* Cleanup */ - memset(key.key, 0, MAX_KEY_SIZE); - /* Copy the key in the driver */ - if(copy_from_user(key.key, - wrq->u.encoding.pointer, - wrq->u.encoding.length)) { - key.len = 0; - rc = -EFAULT; - break; - } - /* Send the key to the card */ - set_wep_key(local, index, key.key, - key.len, 1); - } - /* WE specify that if a valid key is set, encryption - * should be enabled (user may turn it off later) - * This is also how "iwconfig ethX key on" works */ - if((index == current_index) && (key.len > 0) && - (config.authType == AUTH_OPEN)) { - config.authType = AUTH_ENCRYPT; - local->need_commit = 1; - } - } else { - /* Do we want to just set the transmit key index ? */ - int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1; - if ((index>=0) && (index<(cap_rid.softCap&0x80)?4:1)) { - set_wep_key(local, index, 0, 0, 1); - } else - /* Don't complain if only change the mode */ - if(!wrq->u.encoding.flags & IW_ENCODE_MODE) { - rc = -EINVAL; - break; - } + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set Encryption Key + */ +static int airo_set_encode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + CapabilityRid cap_rid; /* Card capability info */ + + /* Is WEP supported ? */ + readCapabilityRid(local, &cap_rid); + /* Older firmware doesn't support this... + if(!(cap_rid.softCap & 2)) { + return -EOPNOTSUPP; + } */ + + /* Basic checking: do we have a key to set ? + * Note : with the new API, it's impossible to get a NULL pointer. + * Therefore, we need to check a key size == 0 instead. + * New version of iwconfig properly set the IW_ENCODE_NOKEY flag + * when no key is present (only change flags), but older versions + * don't do it. - Jean II */ + if (dwrq->length > 0) { + wep_key_t key; + int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + int current_index = get_wep_key(local, 0xffff); + /* Check the size of the key */ + if (dwrq->length > MAX_KEY_SIZE) { + return -EINVAL; } - /* Read the flags */ - if(wrq->u.encoding.flags & IW_ENCODE_DISABLED) - config.authType = AUTH_OPEN; // disable encryption - if(wrq->u.encoding.flags & IW_ENCODE_RESTRICTED) - config.authType = AUTH_SHAREDKEY; // Only Both - if(wrq->u.encoding.flags & IW_ENCODE_OPEN) - config.authType = AUTH_ENCRYPT; // Only Wep - /* Commit the changes if needed */ - if(wrq->u.encoding.flags & IW_ENCODE_MODE) + /* Check the index (none -> use current) */ + if ((index < 0) || (index>=(cap_rid.softCap&0x80)?4:1)) + index = current_index; + /* Set the length */ + if (dwrq->length > MIN_KEY_SIZE) + key.len = MAX_KEY_SIZE; + else + if (dwrq->length > 0) + key.len = MIN_KEY_SIZE; + else + /* Disable the key */ + key.len = 0; + /* Check if the key is not marked as invalid */ + if(!(dwrq->flags & IW_ENCODE_NOKEY)) { + /* Cleanup */ + memset(key.key, 0, MAX_KEY_SIZE); + /* Copy the key in the driver */ + memcpy(key.key, extra, dwrq->length); + /* Send the key to the card */ + set_wep_key(local, index, key.key, key.len, 1); + } + /* WE specify that if a valid key is set, encryption + * should be enabled (user may turn it off later) + * This is also how "iwconfig ethX key on" works */ + if((index == current_index) && (key.len > 0) && + (local->config.authType == AUTH_OPEN)) { + local->config.authType = AUTH_ENCRYPT; local->need_commit = 1; - break; + } + } else { + /* Do we want to just set the transmit key index ? */ + int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + if ((index>=0) && (index<(cap_rid.softCap&0x80)?4:1)) { + set_wep_key(local, index, 0, 0, 1); + } else + /* Don't complain if only change the mode */ + if(!dwrq->flags & IW_ENCODE_MODE) { + return -EINVAL; + } + } + /* Read the flags */ + if(dwrq->flags & IW_ENCODE_DISABLED) + local->config.authType = AUTH_OPEN; // disable encryption + if(dwrq->flags & IW_ENCODE_RESTRICTED) + local->config.authType = AUTH_SHAREDKEY; // Only Both + if(dwrq->flags & IW_ENCODE_OPEN) + local->config.authType = AUTH_ENCRYPT; // Only Wep + /* Commit the changes to flags if needed */ + if(dwrq->flags & IW_ENCODE_MODE) + local->need_commit = 1; + return -EINPROGRESS; /* Call commit handler */ +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get Encryption Key + */ +static int airo_get_encode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + CapabilityRid cap_rid; /* Card capability info */ - // Get the WEP keys and mode - case SIOCGIWENCODE: - /* Is it supported ? */ - if(!(cap_rid.softCap & 2)) { - rc = -EOPNOTSUPP; + /* Is it supported ? */ + readCapabilityRid(local, &cap_rid); + if(!(cap_rid.softCap & 2)) { + return -EOPNOTSUPP; + } + /* Check encryption mode */ + switch(local->config.authType) { + case AUTH_ENCRYPT: + dwrq->flags = IW_ENCODE_OPEN; break; - } - // Only super-user can see WEP key - if (!capable(CAP_NET_ADMIN)) { - rc = -EPERM; + case AUTH_SHAREDKEY: + dwrq->flags = IW_ENCODE_RESTRICTED; break; - } - - // Basic checking... - if (wrq->u.encoding.pointer != (caddr_t) 0) { - char zeros[16]; - int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1; - - memset(zeros,0, sizeof(zeros)); - /* Check encryption mode */ - wrq->u.encoding.flags = IW_ENCODE_NOKEY; - /* Is WEP enabled ??? */ - switch(config.authType) { - case AUTH_ENCRYPT: - wrq->u.encoding.flags |= IW_ENCODE_OPEN; - break; - case AUTH_SHAREDKEY: - wrq->u.encoding.flags |= IW_ENCODE_RESTRICTED; - break; - default: - case AUTH_OPEN: - wrq->u.encoding.flags |= IW_ENCODE_DISABLED; - break; - } + default: + case AUTH_OPEN: + dwrq->flags = IW_ENCODE_DISABLED; + break; + } + /* We can't return the key, so set the proper flag and return zero */ + dwrq->flags |= IW_ENCODE_NOKEY; + memset(extra, 0, 16); + + /* Which key do we want ? -1 -> tx index */ + if((index < 0) || (index >= (cap_rid.softCap & 0x80) ? 4 : 1)) + index = get_wep_key(local, 0xffff); + dwrq->flags |= index + 1; + /* Copy the key to the user buffer */ + dwrq->length = get_wep_key(local, index); + if (dwrq->length > 16) { + dwrq->length=0; + } + return 0; +} - /* Which key do we want ? -1 -> tx index */ - if((index < 0) || (index >= (cap_rid.softCap&0x80)?4:1)) - index = get_wep_key(local, 0xffff); - wrq->u.encoding.flags |= index + 1; - /* Copy the key to the user buffer */ - wrq->u.encoding.length = get_wep_key(local, index); - if (wrq->u.encoding.length > 16) { - wrq->u.encoding.length=0; - } +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set Tx-Power + */ +static int airo_set_txpow(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + CapabilityRid cap_rid; /* Card capability info */ + int i; + int rc = -EINVAL; - if(copy_to_user(wrq->u.encoding.pointer, zeros, - wrq->u.encoding.length)) - rc = -EFAULT; - } - break; + readCapabilityRid(local, &cap_rid); -#if WIRELESS_EXT > 9 - // Get the current Tx-Power - case SIOCGIWTXPOW: - wrq->u.txpower.value = config.txPower; - wrq->u.txpower.fixed = 1; /* No power control */ - wrq->u.txpower.disabled = (local->flags & FLAG_RADIO_OFF); - wrq->u.txpower.flags = IW_TXPOW_MWATT; - break; - case SIOCSIWTXPOW: - if (wrq->u.txpower.disabled) { - local->flags |= FLAG_RADIO_OFF; + if (vwrq->disabled) { + local->flags |= FLAG_RADIO_OFF; + local->need_commit = 1; + return -EINPROGRESS; /* Call commit handler */ + } + if (vwrq->flags != IW_TXPOW_MWATT) { + return -EINVAL; + } + local->flags &= ~FLAG_RADIO_OFF; + for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++) + if ((vwrq->value==cap_rid.txPowerLevels[i])) { + local->config.txPower = vwrq->value; local->need_commit = 1; + rc = -EINPROGRESS; /* Call commit handler */ break; } - if (wrq->u.txpower.flags != IW_TXPOW_MWATT) { - rc = -EINVAL; - break; + return rc; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get Tx-Power + */ +static int airo_get_txpow(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + + vwrq->value = local->config.txPower; + vwrq->fixed = 1; /* No power control */ + vwrq->disabled = (local->flags & FLAG_RADIO_OFF); + vwrq->flags = IW_TXPOW_MWATT; + + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set Retry limits + */ +static int airo_set_retry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + int rc = -EINVAL; + + if(vwrq->disabled) { + return -EINVAL; + } + if(vwrq->flags & IW_RETRY_LIMIT) { + if(vwrq->flags & IW_RETRY_MAX) + local->config.longRetryLimit = vwrq->value; + else if (vwrq->flags & IW_RETRY_MIN) + local->config.shortRetryLimit = vwrq->value; + else { + /* No modifier : set both */ + local->config.longRetryLimit = vwrq->value; + local->config.shortRetryLimit = vwrq->value; } - local->flags &= ~FLAG_RADIO_OFF; - rc = -EINVAL; - for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++) - if ((wrq->u.txpower.value==cap_rid.txPowerLevels[i])) { - config.txPower = wrq->u.txpower.value; - local->need_commit = 1; - rc = 0; - break; - } - break; -#endif /* WIRELESS_EXT > 9 */ + local->need_commit = 1; + rc = -EINPROGRESS; /* Call commit handler */ + } + if(vwrq->flags & IW_RETRY_LIFETIME) { + local->config.txLifetime = vwrq->value / 1024; + local->need_commit = 1; + rc = -EINPROGRESS; /* Call commit handler */ + } + return rc; +} -#if WIRELESS_EXT > 10 - case SIOCSIWRETRY: - if(wrq->u.retry.disabled) { - rc = -EINVAL; +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get Retry limits + */ +static int airo_get_retry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + + vwrq->disabled = 0; /* Can't be disabled */ + + /* Note : by default, display the min retry number */ + if((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { + vwrq->flags = IW_RETRY_LIFETIME; + vwrq->value = (int)local->config.txLifetime * 1024; + } else if((vwrq->flags & IW_RETRY_MAX)) { + vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; + vwrq->value = (int)local->config.longRetryLimit; + } else { + vwrq->flags = IW_RETRY_LIMIT; + vwrq->value = (int)local->config.shortRetryLimit; + if((int)local->config.shortRetryLimit != (int)local->config.longRetryLimit) + vwrq->flags |= IW_RETRY_MIN; + } + + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get range info + */ +static int airo_get_range(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + struct iw_range *range = (struct iw_range *) extra; + CapabilityRid cap_rid; /* Card capability info */ + int i; + int k; + + readCapabilityRid(local, &cap_rid); + + dwrq->length = sizeof(struct iw_range); + memset(range, 0, sizeof(range)); + range->min_nwid = 0x0000; + range->max_nwid = 0x0000; + range->num_channels = 14; + /* Should be based on cap_rid.country to give only + * what the current card support */ + k = 0; + for(i = 0; i < 14; i++) { + range->freq[k].i = i + 1; /* List index */ + range->freq[k].m = frequency_list[i] * 100000; + range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */ + } + range->num_frequency = k; + + /* Hum... Should put the right values there */ + range->max_qual.qual = 10; + range->max_qual.level = 0x100 - 120; /* -120 dBm */ + range->max_qual.noise = 0; + range->sensitivity = 65535; + + for(i = 0 ; i < 8 ; i++) { + range->bitrate[i] = cap_rid.supportedRates[i] * 500000; + if(range->bitrate[i] == 0) + break; + } + range->num_bitrates = i; + + /* Set an indication of the max TCP throughput + * in bit/s that we can expect using this interface. + * May be use for QoS stuff... Jean II */ + if(i > 2) + range->throughput = 5000 * 1000; + else + range->throughput = 1500 * 1000; + + range->min_rts = 0; + range->max_rts = 2312; + range->min_frag = 256; + range->max_frag = 2312; + + if(cap_rid.softCap & 2) { + // WEP: RC4 40 bits + range->encoding_size[0] = 5; + // RC4 ~128 bits + if (cap_rid.softCap & 0x100) { + range->encoding_size[1] = 13; + range->num_encoding_sizes = 2; + } else + range->num_encoding_sizes = 1; + range->max_encoding_tokens = (cap_rid.softCap & 0x80) ? 4 : 1; + } else { + range->num_encoding_sizes = 0; + range->max_encoding_tokens = 0; + } + range->min_pmp = 0; + range->max_pmp = 5000000; /* 5 secs */ + range->min_pmt = 0; + range->max_pmt = 65535 * 1024; /* ??? */ + range->pmp_flags = IW_POWER_PERIOD; + range->pmt_flags = IW_POWER_TIMEOUT; + range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; + + /* Transmit Power - values are in mW */ + for(i = 0 ; i < 8 ; i++) { + range->txpower[i] = cap_rid.txPowerLevels[i]; + if(range->txpower[i] == 0) break; + } + range->num_txpower = i; + range->txpower_capa = IW_TXPOW_MWATT; + range->we_version_source = 12; + range->we_version_compiled = WIRELESS_EXT; + range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; + range->retry_flags = IW_RETRY_LIMIT; + range->r_time_flags = IW_RETRY_LIFETIME; + range->min_retry = 1; + range->max_retry = 65535; + range->min_r_time = 1024; + range->max_r_time = 65535 * 1024; + /* Experimental measurements - boundary 11/5.5 Mb/s */ + /* Note : with or without the (local->rssi), results + * are somewhat different. - Jean II */ + range->avg_qual.qual = 6; + if (local->rssi) + range->avg_qual.level = 186; /* -70 dBm */ + else + range->avg_qual.level = 176; /* -80 dBm */ + range->avg_qual.noise = 0; + + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set Power Management + */ +static int airo_set_power(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + + if (vwrq->disabled) { + if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) { + return -EINVAL; } - local->need_commit = 0; - if(wrq->u.retry.flags & IW_RETRY_LIMIT) { - if(wrq->u.retry.flags & IW_RETRY_MAX) - config.longRetryLimit = wrq->u.retry.value; - else if (wrq->u.retry.flags & IW_RETRY_MIN) - config.shortRetryLimit = wrq->u.retry.value; - else { - /* No modifier : set both */ - config.longRetryLimit = wrq->u.retry.value; - config.shortRetryLimit = wrq->u.retry.value; + local->config.powerSaveMode = POWERSAVE_CAM; + local->config.rmode &= 0xFF00; + local->config.rmode |= RXMODE_BC_MC_ADDR; + local->need_commit = 1; + return -EINPROGRESS; /* Call commit handler */ + } + if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { + local->config.fastListenDelay = (vwrq->value + 500) / 1024; + local->config.powerSaveMode = POWERSAVE_PSPCAM; + local->need_commit = 1; + } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { + local->config.fastListenInterval = local->config.listenInterval = (vwrq->value + 500) / 1024; + local->config.powerSaveMode = POWERSAVE_PSPCAM; + local->need_commit = 1; + } + switch (vwrq->flags & IW_POWER_MODE) { + case IW_POWER_UNICAST_R: + if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) { + return -EINVAL; } + local->config.rmode &= 0xFF00; + local->config.rmode |= RXMODE_ADDR; local->need_commit = 1; - } - if(wrq->u.retry.flags & IW_RETRY_LIFETIME) { - config.txLifetime = wrq->u.retry.value / 1024; + break; + case IW_POWER_ALL_R: + if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) { + return -EINVAL; + } + local->config.rmode &= 0xFF00; + local->config.rmode |= RXMODE_BC_MC_ADDR; local->need_commit = 1; - } - if(local->need_commit == 0) { - rc = -EINVAL; - } - break; + case IW_POWER_ON: + break; + default: + return -EINVAL; + } + // Note : we may want to factor local->need_commit here + // Note2 : may also want to factor RXMODE_RFMON test + return -EINPROGRESS; /* Call commit handler */ +} - case SIOCGIWRETRY: - wrq->u.retry.disabled = 0; /* Can't be disabled */ +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get Power Management + */ +static int airo_get_power(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; - /* Note : by default, display the min retry number */ - if((wrq->u.retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { - wrq->u.retry.flags = IW_RETRY_LIFETIME; - wrq->u.retry.value = (int)config.txLifetime * 1024; - } else if((wrq->u.retry.flags & IW_RETRY_MAX)) { - wrq->u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - wrq->u.retry.value = (int)config.longRetryLimit; - } else { - wrq->u.retry.flags = IW_RETRY_LIMIT; - wrq->u.retry.value = (int)config.shortRetryLimit; - if((int)config.shortRetryLimit != (int)config.longRetryLimit) - wrq->u.retry.flags |= IW_RETRY_MIN; - } + int mode = local->config.powerSaveMode; + if ((vwrq->disabled = (mode == POWERSAVE_CAM))) + return 0; + if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { + vwrq->value = (int)local->config.fastListenDelay * 1024; + vwrq->flags = IW_POWER_TIMEOUT; + } else { + vwrq->value = (int)local->config.fastListenInterval * 1024; + vwrq->flags = IW_POWER_PERIOD; + } + if ((local->config.rmode & 0xFF) == RXMODE_ADDR) + vwrq->flags |= IW_POWER_UNICAST_R; + else + vwrq->flags |= IW_POWER_ALL_R; - break; -#endif /* WIRELESS_EXT > 10 */ + return 0; +} - // Get range of parameters - case SIOCGIWRANGE: - if (wrq->u.data.pointer) { - struct iw_range range; - int i; - int k; +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set Sensitivity + */ +static int airo_set_sens(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; - wrq->u.data.length = sizeof(range); - memset(&range, 0, sizeof(range)); - range.min_nwid = 0x0000; - range.max_nwid = 0x0000; - range.num_channels = 14; - /* Should be based on cap_rid.country to give only - * what the current card support */ - k = 0; - for(i = 0; i < 14; i++) { - range.freq[k].i = i + 1; /* List index */ - range.freq[k].m = frequency_list[i] * 100000; - range.freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */ - } - range.num_frequency = k; - - /* Hum... Should put the right values there */ - range.max_qual.qual = 10; - range.max_qual.level = 0x100 - 120; /* -120 dBm */ - range.max_qual.noise = 0; - range.sensitivity = 65535; - - for(i = 0 ; i < 8 ; i++) { - range.bitrate[i] = cap_rid.supportedRates[i] * 500000; - if(range.bitrate[i] == 0) - break; - } - range.num_bitrates = i; + local->config.rssiThreshold = vwrq->disabled ? RSSI_DEFAULT : vwrq->value; + local->need_commit = 1; - /* Set an indication of the max TCP throughput - * in bit/s that we can expect using this interface. - * May be use for QoS stuff... Jean II */ - if(i > 2) - range.throughput = 5 * 1000 * 1000; - else - range.throughput = 1.5 * 1000 * 1000; + return -EINPROGRESS; /* Call commit handler */ +} - range.min_rts = 0; - range.max_rts = 2312; - range.min_frag = 256; - range.max_frag = 2312; - - if(cap_rid.softCap & 2) { - // WEP: RC4 40 bits - range.encoding_size[0] = 5; - // RC4 ~128 bits - if (cap_rid.softCap & 0x100) { - range.encoding_size[1] = 13; - range.num_encoding_sizes = 2; - } else - range.num_encoding_sizes = 1; - range.max_encoding_tokens = (cap_rid.softCap & 0x80) ? 4 : 1; - } else { - range.num_encoding_sizes = 0; - range.max_encoding_tokens = 0; - } -#if WIRELESS_EXT > 9 - range.min_pmp = 0; - range.max_pmp = 5000000; /* 5 secs */ - range.min_pmt = 0; - range.max_pmt = 65535 * 1024; /* ??? */ - range.pmp_flags = IW_POWER_PERIOD; - range.pmt_flags = IW_POWER_TIMEOUT; - range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; - - /* Transmit Power - values are in mW */ - for(i = 0 ; i < 8 ; i++) { - range.txpower[i] = cap_rid.txPowerLevels[i]; - if(range.txpower[i] == 0) - break; - } - range.num_txpower = i; - range.txpower_capa = IW_TXPOW_MWATT; -#endif /* WIRELESS_EXT > 9 */ -#if WIRELESS_EXT > 10 - range.we_version_source = 12; - range.we_version_compiled = WIRELESS_EXT; - range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; - range.retry_flags = IW_RETRY_LIMIT; - range.r_time_flags = IW_RETRY_LIFETIME; - range.min_retry = 1; - range.max_retry = 65535; - range.min_r_time = 1024; - range.max_r_time = 65535 * 1024; -#endif /* WIRELESS_EXT > 10 */ -#if WIRELESS_EXT > 11 - /* Experimental measurements - boundary 11/5.5 Mb/s */ - /* Note : with or without the (local->rssi), results - * are somewhat different. - Jean II */ - range.avg_qual.qual = 6; - if (local->rssi) - range.avg_qual.level = 186; /* -70 dBm */ - else - range.avg_qual.level = 176; /* -80 dBm */ - range.avg_qual.noise = 0; -#endif /* WIRELESS_EXT > 11 */ +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get Sensitivity + */ +static int airo_get_sens(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *local = dev->priv; - if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range))) - rc = -EFAULT; - } - break; + vwrq->value = local->config.rssiThreshold; + vwrq->disabled = (vwrq->value == 0); + vwrq->fixed = 1; - case SIOCGIWPOWER: - { - int mode = config.powerSaveMode; - if ((wrq->u.power.disabled = (mode == POWERSAVE_CAM))) + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get AP List + * Note : this is deprecated in favor of IWSCAN + */ +static int airo_get_aplist(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + struct sockaddr *address = (struct sockaddr *) extra; + struct iw_quality qual[IW_MAX_AP]; + BSSListRid BSSList; + int i; + int loseSync = capable(CAP_NET_ADMIN) ? 1: -1; + + for (i = 0; i < IW_MAX_AP; i++) { + if (readBSSListRid(local, loseSync, &BSSList)) break; - if ((wrq->u.power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - wrq->u.power.value = (int)config.fastListenDelay * 1024; - wrq->u.power.flags = IW_POWER_TIMEOUT; - } else { - wrq->u.power.value = (int)config.fastListenInterval * 1024; - wrq->u.power.flags = IW_POWER_PERIOD; + loseSync = 0; + memcpy(address[i].sa_data, BSSList.bssid, 6); + address[i].sa_family = ARPHRD_ETHER; + if (local->rssi) + qual[i].level = 0x100 - local->rssi[BSSList.rssi].rssidBm; + else + qual[i].level = (BSSList.rssi + 321) / 2; + qual[i].qual = qual[i].noise = 0; + qual[i].updated = 2; + if (BSSList.index == 0xffff) + break; + } + if (!i) { + StatusRid status_rid; /* Card status info */ + readStatusRid(local, &status_rid); + for (i = 0; + i < min(IW_MAX_AP, 4) && + (status_rid.bssid[i][0] + & status_rid.bssid[i][1] + & status_rid.bssid[i][2] + & status_rid.bssid[i][3] + & status_rid.bssid[i][4] + & status_rid.bssid[i][5])!=-1 && + (status_rid.bssid[i][0] + | status_rid.bssid[i][1] + | status_rid.bssid[i][2] + | status_rid.bssid[i][3] + | status_rid.bssid[i][4] + | status_rid.bssid[i][5]); + i++) { + memcpy(address[i].sa_data, + status_rid.bssid[i], 6); + address[i].sa_family = ARPHRD_ETHER; } - if ((config.rmode & 0xFF) == RXMODE_ADDR) - wrq->u.power.flags |= IW_POWER_UNICAST_R; + } else { + dwrq->flags = 1; /* Should be define'd */ + memcpy(extra + sizeof(struct sockaddr)*i, + &qual, sizeof(struct iw_quality)*i); + } + dwrq->length = i; + + return 0; +} + +#if WIRELESS_EXT > 13 +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : Initiate Scan + */ +static int airo_set_scan(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra) +{ + struct airo_info *ai = dev->priv; + Cmd cmd; + Resp rsp; + + /* Note : you may have realised that, as this is a SET operation, + * this is priviledged and therefore a normal user can't + * perform scanning. + * This is not an error, while the device perform scanning, + * traffic doesn't flow, so it's a perfect DoS... + * Jean II */ + + /* Initiate a scan command */ + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd=CMD_LISTBSS; + if (down_interruptible(&ai->sem)) + return -ERESTARTSYS; + issuecommand(ai, &cmd, &rsp); + ai->scan_timestamp = jiffies; + up(&ai->sem); + + /* At this point, just return to the user. */ + + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Translate scan data returned from the card to a card independant + * format that the Wireless Tools will understand - Jean II + */ +static inline char *airo_translate_scan(struct net_device *dev, + char *current_ev, + char *end_buf, + BSSListRid *list) +{ + struct airo_info *ai = dev->priv; + struct iw_event iwe; /* Temporary buffer */ + u16 capabilities; + char * current_val; /* For rates */ + int i; + + /* First entry *MUST* be the AP MAC address */ + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, list->bssid, ETH_ALEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); + + /* Other entries will be displayed in the order we give them */ + + /* Add the ESSID */ + iwe.u.data.length = list->ssidLen; + if(iwe.u.data.length > 32) + iwe.u.data.length = 32; + iwe.cmd = SIOCGIWESSID; + iwe.u.data.flags = 1; + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid); + + /* Add mode */ + iwe.cmd = SIOCGIWMODE; + capabilities = le16_to_cpu(list->cap); + if(capabilities & (CAP_ESS | CAP_IBSS)) { + if(capabilities & CAP_ESS) + iwe.u.mode = IW_MODE_INFRA; else - wrq->u.power.flags |= IW_POWER_ALL_R; + iwe.u.mode = IW_MODE_ADHOC; + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN); } - break; - case SIOCSIWPOWER: - if (wrq->u.power.disabled) { - if ((config.rmode & 0xFF) >= RXMODE_RFMON) { - rc = -EINVAL; + /* Add frequency */ + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = le16_to_cpu(list->dsChannel); + iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000; + iwe.u.freq.e = 1; + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); + + /* Add quality statistics */ + iwe.cmd = IWEVQUAL; + if (ai->rssi) + iwe.u.qual.level = 0x100 - ai->rssi[list->rssi].rssidBm; + else + iwe.u.qual.level = (list->rssi + 321) / 2; + iwe.u.qual.noise = 0; + iwe.u.qual.qual = 0; + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + + /* Add encryption capability */ + iwe.cmd = SIOCGIWENCODE; + if(capabilities & CAP_PRIVACY) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + iwe.u.data.length = 0; + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid); + + /* Rate : stuffing multiple values in a single event require a bit + * more of magic - Jean II */ + current_val = current_ev + IW_EV_LCP_LEN; + + iwe.cmd = SIOCGIWRATE; + /* Those two flags are ignored... */ + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + /* Max 8 values */ + for(i = 0 ; i < 8 ; i++) { + /* NULL terminated */ + if(list->rates[i] == 0) + break; + /* Bit rate given in 500 kb/s units (+ 0x80) */ + iwe.u.bitrate.value = ((list->rates[i] & 0x7f) * 500000); + /* Add new value to event */ + current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); + } + /* Check if we added any event */ + if((current_val - current_ev) > IW_EV_LCP_LEN) + current_ev = current_val; + + /* The other data in the scan result are not really + * interesting, so for now drop it - Jean II */ + return current_ev; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : Read Scan Results + */ +static int airo_get_scan(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra) +{ + struct airo_info *ai = dev->priv; + BSSListRid BSSList; + int rc; + char *current_ev = extra; + + /* When we are associated again, the scan has surely finished. + * Just in case, let's make sure enough time has elapsed since + * we started the scan. - Javier */ + if(ai->scan_timestamp && time_before(jiffies,ai->scan_timestamp+3*HZ)) { + /* Important note : we don't want to block the caller + * until results are ready for various reasons. + * First, managing wait queues is complex and racy + * (there may be multiple simultaneous callers). + * Second, we grab some rtnetlink lock before comming + * here (in dev_ioctl()). + * Third, the caller can wait on the Wireless Event + * - Jean II */ + return -EAGAIN; + } + ai->scan_timestamp = 0; + + /* There's only a race with proc_BSSList_open(), but its + * consequences are begnign. So I don't bother fixing it - Javier */ + + /* Try to read the first entry of the scan result */ + rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList)); + if((rc) || (BSSList.index == 0xffff)) { + /* Client error, no scan results... + * The caller need to restart the scan. */ + return -ENODATA; + } + + /* Read and parse all entries */ + while((!rc) && (BSSList.index != 0xffff)) { + /* Translate to WE format this entry */ + current_ev = airo_translate_scan(dev, current_ev, + extra + IW_SCAN_MAX_DATA, + &BSSList); + + /* Read next entry */ + rc = PC4500_readrid(ai, RID_BSSLISTNEXT, + &BSSList, sizeof(BSSList)); + } + /* Length of data */ + dwrq->length = (current_ev - extra); + dwrq->flags = 0; /* todo */ + + return 0; +} +#endif /* WIRELESS_EXT > 13 */ + +#ifdef WIRELESS_SPY +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set Spy List + */ +static int airo_set_spy(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + struct sockaddr *address = (struct sockaddr *) extra; + + /* Disable spy while we copy the addresses. + * As we don't disable interrupts, we need to do this to avoid races */ + local->spy_number = 0; + + if (dwrq->length > 0) { + int i; + + /* Copy addresses */ + for (i = 0; i < dwrq->length; i++) + memcpy(local->spy_address[i], address[i].sa_data, 6); + /* Reset stats */ + memset(local->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY); + } + /* Enable addresses */ + local->spy_number = dwrq->length; + + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get Spy List + */ +static int airo_get_spy(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra) +{ + struct airo_info *local = dev->priv; + struct sockaddr *address = (struct sockaddr *) extra; + int i; + + dwrq->length = local->spy_number; + + /* Copy addresses. */ + for(i = 0; i < local->spy_number; i++) { + memcpy(address[i].sa_data, local->spy_address[i], 6); + address[i].sa_family = AF_UNIX; + } + /* Copy stats to the user buffer (just after). */ + if(local->spy_number > 0) + memcpy(extra + (sizeof(struct sockaddr) * local->spy_number), + local->spy_stat, sizeof(struct iw_quality) * local->spy_number); + /* Reset updated flags. */ + for (i=0; ispy_number; i++) + local->spy_stat[i].updated = 0; + return 0; +} +#endif /* WIRELESS_SPY */ + +/*------------------------------------------------------------------*/ +/* + * Commit handler : called after a bunch of SET operations + */ +static int airo_config_commit(struct net_device *dev, + struct iw_request_info *info, /* NULL */ + void *zwrq, /* NULL */ + char *extra) /* NULL */ +{ + struct airo_info *local = dev->priv; + Resp rsp; + + if (!local->need_commit) + return 0; + + /* Some of the "SET" function may have modified some of the + * parameters. It's now time to commit them in the card */ + disable_MAC(local); + writeConfigRid(local); + enable_MAC(local, &rsp); + + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Structures to export the Wireless Handlers + */ + +static const struct iw_priv_args airo_private_args[] = { +/*{ cmd, set_args, get_args, name } */ + { AIROIOCTL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl), + IW_PRIV_TYPE_BYTE | 2047, "airoioctl" }, + { AIROIDIFC, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl), + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "airoidifc" }, +}; + +#if WIRELESS_EXT > 12 +static const iw_handler airo_handler[] = +{ + (iw_handler) airo_config_commit, /* SIOCSIWCOMMIT */ + (iw_handler) airo_get_name, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) airo_set_freq, /* SIOCSIWFREQ */ + (iw_handler) airo_get_freq, /* SIOCGIWFREQ */ + (iw_handler) airo_set_mode, /* SIOCSIWMODE */ + (iw_handler) airo_get_mode, /* SIOCGIWMODE */ + (iw_handler) airo_set_sens, /* SIOCSIWSENS */ + (iw_handler) airo_get_sens, /* SIOCGIWSENS */ + (iw_handler) NULL, /* SIOCSIWRANGE */ + (iw_handler) airo_get_range, /* SIOCGIWRANGE */ + (iw_handler) NULL, /* SIOCSIWPRIV */ + (iw_handler) NULL, /* SIOCGIWPRIV */ + (iw_handler) NULL, /* SIOCSIWSTATS */ + (iw_handler) NULL, /* SIOCGIWSTATS */ +#ifdef WIRELESS_SPY + (iw_handler) airo_set_spy, /* SIOCSIWSPY */ + (iw_handler) airo_get_spy, /* SIOCGIWSPY */ +#else /* WIRELESS_SPY */ + (iw_handler) NULL, /* SIOCSIWSPY */ + (iw_handler) NULL, /* SIOCGIWSPY */ +#endif /* WIRELESS_SPY */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) airo_set_wap, /* SIOCSIWAP */ + (iw_handler) airo_get_wap, /* SIOCGIWAP */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) airo_get_aplist, /* SIOCGIWAPLIST */ +#if WIRELESS_EXT > 13 + (iw_handler) airo_set_scan, /* SIOCSIWSCAN */ + (iw_handler) airo_get_scan, /* SIOCGIWSCAN */ +#else /* WIRELESS_EXT > 13 */ + (iw_handler) NULL, /* SIOCSIWSCAN */ + (iw_handler) NULL, /* SIOCGIWSCAN */ +#endif /* WIRELESS_EXT > 13 */ + (iw_handler) airo_set_essid, /* SIOCSIWESSID */ + (iw_handler) airo_get_essid, /* SIOCGIWESSID */ + (iw_handler) airo_set_nick, /* SIOCSIWNICKN */ + (iw_handler) airo_get_nick, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) airo_set_rate, /* SIOCSIWRATE */ + (iw_handler) airo_get_rate, /* SIOCGIWRATE */ + (iw_handler) airo_set_rts, /* SIOCSIWRTS */ + (iw_handler) airo_get_rts, /* SIOCGIWRTS */ + (iw_handler) airo_set_frag, /* SIOCSIWFRAG */ + (iw_handler) airo_get_frag, /* SIOCGIWFRAG */ + (iw_handler) airo_set_txpow, /* SIOCSIWTXPOW */ + (iw_handler) airo_get_txpow, /* SIOCGIWTXPOW */ + (iw_handler) airo_set_retry, /* SIOCSIWRETRY */ + (iw_handler) airo_get_retry, /* SIOCGIWRETRY */ + (iw_handler) airo_set_encode, /* SIOCSIWENCODE */ + (iw_handler) airo_get_encode, /* SIOCGIWENCODE */ + (iw_handler) airo_set_power, /* SIOCSIWPOWER */ + (iw_handler) airo_get_power, /* SIOCGIWPOWER */ +}; + +/* Note : don't describe AIROIDIFC and AIROOLDIDIFC in here. + * We want to force the use of the ioctl code, because those can't be + * won't work the iw_handler code (because they simultaneously read + * and write data and iw_handler can't do that). + * Note that it's perfectly legal to read/write on a single ioctl command, + * you just can't use iwpriv and need to force it via the ioctl handler. + * Jean II */ +static const iw_handler airo_private_handler[] = +{ + NULL, /* SIOCIWFIRSTPRIV */ +}; + +static const struct iw_handler_def airo_handler_def = +{ + num_standard: sizeof(airo_handler)/sizeof(iw_handler), + num_private: sizeof(airo_private_handler)/sizeof(iw_handler), + num_private_args: sizeof(airo_private_args)/sizeof(struct iw_priv_args), + standard: (iw_handler *) airo_handler, + private: (iw_handler *) airo_private_handler, + private_args: (struct iw_priv_args *) airo_private_args, +}; + +#endif /* WIRELESS_EXT > 12 */ +#endif /* WIRELESS_EXT */ + +/* + * This defines the configuration part of the Wireless Extensions + * Note : irq and spinlock protection will occur in the subroutines + * + * TODO : + * o Check input value more carefully and fill correct values in range + * o Test and shakeout the bugs (if any) + * + * Jean II + * + * Javier Achirica did a great job of merging code from the unnamed CISCO + * developer that added support for flashing the card. + */ +static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + int rc = 0; +#if defined(WIRELESS_EXT) && WIRELESS_EXT < 13 + struct iwreq *wrq = (struct iwreq *) rq; +#endif /* WIRELESS_EXT < 13 */ + + switch (cmd) { +/* WE 13 and higher will use airo_handler_def */ +#if defined(WIRELESS_EXT) && WIRELESS_EXT < 13 + case SIOCGIWNAME: // Get name + airo_get_name(dev, NULL, (char *) &(wrq->u.name), NULL); + break; + + case SIOCSIWFREQ: // Set frequency/channel + rc = airo_set_freq(dev, NULL, &(wrq->u.freq), NULL); + break; + + case SIOCGIWFREQ: // Get frequency/channel + rc = airo_get_freq(dev, NULL, &(wrq->u.freq), NULL); + break; + + case SIOCSIWESSID: // Set desired network name (ESSID) + { + char essidbuf[IW_ESSID_MAX_SIZE+1]; + if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) { + rc = -E2BIG; break; } - config.powerSaveMode = POWERSAVE_CAM; - config.rmode &= 0xFF00; - config.rmode |= RXMODE_BC_MC_ADDR; - local->need_commit = 1; - break; + if (copy_from_user(essidbuf, wrq->u.essid.pointer, + wrq->u.essid.length)) { + rc = -EFAULT; + break; + } + rc = airo_set_essid(dev, NULL, + &(wrq->u.essid), essidbuf); } - if ((wrq->u.power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - config.fastListenDelay = (wrq->u.power.value + 500) / 1024; - config.powerSaveMode = POWERSAVE_PSPCAM; - local->need_commit = 1; - } else if ((wrq->u.power.flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { - config.fastListenInterval = config.listenInterval = (wrq->u.power.value + 500) / 1024; - config.powerSaveMode = POWERSAVE_PSPCAM; - local->need_commit = 1; + break; + + case SIOCGIWESSID: // Get current network name (ESSID) + { + char essidbuf[IW_ESSID_MAX_SIZE+1]; + if (wrq->u.essid.pointer) + rc = airo_get_essid(dev, NULL, + &(wrq->u.essid), essidbuf); + if ( copy_to_user(wrq->u.essid.pointer, + essidbuf, + wrq->u.essid.length) ) + rc = -EFAULT; } - switch (wrq->u.power.flags & IW_POWER_MODE) { - case IW_POWER_UNICAST_R: - if ((config.rmode & 0xFF) >= RXMODE_RFMON) { - rc = -EINVAL; + break; + + case SIOCSIWAP: + rc = airo_set_wap(dev, NULL, &(wrq->u.ap_addr), NULL); + break; + + case SIOCGIWAP: // Get current Access Point (BSSID) + rc = airo_get_wap(dev, NULL, &(wrq->u.ap_addr), NULL); + break; + + case SIOCSIWNICKN: // Set desired station name + { + char nickbuf[IW_ESSID_MAX_SIZE+1]; + if (wrq->u.data.length > IW_ESSID_MAX_SIZE) { + rc = -E2BIG; break; } - config.rmode &= 0xFF00; - config.rmode |= RXMODE_ADDR; - local->need_commit = 1; - break; - case IW_POWER_ALL_R: - if ((config.rmode & 0xFF) >= RXMODE_RFMON) { - rc = -EINVAL; + if (copy_from_user(nickbuf, wrq->u.data.pointer, + wrq->u.data.length)) { + rc = -EFAULT; break; } - config.rmode &= 0xFF00; - config.rmode |= RXMODE_BC_MC_ADDR; - local->need_commit = 1; - case IW_POWER_ON: - break; - default: - rc = -EINVAL; + rc = airo_set_nick(dev, NULL, + &(wrq->u.data), nickbuf); } break; - case SIOCGIWSENS: - wrq->u.sens.value = config.rssiThreshold; - wrq->u.sens.disabled = (wrq->u.sens.value == 0); - wrq->u.sens.fixed = 1; + case SIOCGIWNICKN: // Get current station name + { + char nickbuf[IW_ESSID_MAX_SIZE+1]; + if (wrq->u.data.pointer) + rc = airo_get_nick(dev, NULL, + &(wrq->u.data), nickbuf); + if ( copy_to_user(wrq->u.data.pointer, + nickbuf, + wrq->u.data.length) ) + rc = -EFAULT; + } break; - case SIOCSIWSENS: - config.rssiThreshold = wrq->u.sens.disabled ? RSSI_DEFAULT : wrq->u.sens.value; - local->need_commit = 1; + case SIOCSIWRATE: // Set the desired bit-rate + rc = airo_set_rate(dev, NULL, &(wrq->u.bitrate), NULL); break; - case SIOCGIWAPLIST: - if (wrq->u.data.pointer) { - int i, rc; - struct sockaddr s[IW_MAX_AP]; - struct iw_quality qual[IW_MAX_AP]; - BSSListRid BSSList; - int loseSync = capable(CAP_NET_ADMIN) ? 1: -1; - for (i = 0; i < IW_MAX_AP; i++) { - if (readBSSListRid(local, loseSync, &BSSList)) + case SIOCGIWRATE: // Get the current bit-rate + rc = airo_get_rate(dev, NULL, &(wrq->u.bitrate), NULL); + break; + + case SIOCSIWRTS: // Set the desired RTS threshold + rc = airo_set_rts(dev, NULL, &(wrq->u.rts), NULL); + break; + + case SIOCGIWRTS: // Get the current RTS threshold + rc = airo_get_rts(dev, NULL, &(wrq->u.rts), NULL); + break; + + case SIOCSIWFRAG: // Set the desired fragmentation threshold + rc = airo_set_frag(dev, NULL, &(wrq->u.frag), NULL); + break; + + case SIOCGIWFRAG: // Get the current fragmentation threshold + rc = airo_get_frag(dev, NULL, &(wrq->u.frag), NULL); + break; + + case SIOCSIWMODE: // Set mode of operation + rc = airo_set_mode(dev, NULL, &(wrq->u.mode), NULL); + break; + + case SIOCGIWMODE: // Get mode of operation + rc = airo_get_mode(dev, NULL, &(wrq->u.mode), NULL); + break; + + case SIOCSIWENCODE: // Set WEP keys and mode + { + char keybuf[MAX_KEY_SIZE]; + if (wrq->u.encoding.pointer) { + /* We actually have a key to set */ + if (wrq->u.encoding.length > MAX_KEY_SIZE) { + rc = -E2BIG; break; - loseSync = 0; - memcpy(s[i].sa_data, BSSList.bssid, 6); - s[i].sa_family = ARPHRD_ETHER; - if (local->rssi) - qual[i].level = 0x100 - local->rssi[BSSList.rssi].rssidBm; - else - qual[i].level = (BSSList.rssi + 321) / 2; - qual[i].qual = qual[i].noise = 0; - qual[i].updated = 2; - if (BSSList.index == 0xffff) break; - } - if (!i) { - for (i = 0; - i < min(IW_MAX_AP, 4) && - (status_rid.bssid[i][0] - & status_rid.bssid[i][1] - & status_rid.bssid[i][2] - & status_rid.bssid[i][3] - & status_rid.bssid[i][4] - & status_rid.bssid[i][5])!=-1 && - (status_rid.bssid[i][0] - | status_rid.bssid[i][1] - | status_rid.bssid[i][2] - | status_rid.bssid[i][3] - | status_rid.bssid[i][4] - | status_rid.bssid[i][5]); - i++) { - memcpy(s[i].sa_data, - status_rid.bssid[i], 6); - s[i].sa_family = ARPHRD_ETHER; } - } else { - wrq->u.data.flags = 1; /* Should be define'd */ - if (copy_to_user(wrq->u.data.pointer - + sizeof(struct sockaddr)*i, - &qual, - sizeof(struct iw_quality)*i)) + if (copy_from_user(keybuf, + wrq->u.encoding.pointer, + wrq->u.encoding.length)) { rc = -EFAULT; + break; + } + } else if (wrq->u.encoding.length != 0) { + rc = -EINVAL; + break; } - wrq->u.data.length = i; - if (copy_to_user(wrq->u.data.pointer, &s, - sizeof(struct sockaddr)*i)) - rc = -EFAULT; + rc = airo_set_encode(dev, NULL, + &(wrq->u.encoding), keybuf); } break; -#ifdef WIRELESS_SPY - // Set the spy list - case SIOCSIWSPY: - if (wrq->u.data.length > IW_MAX_SPY) - { - rc = -E2BIG; + case SIOCGIWENCODE: // Get the WEP keys and mode + // Only super-user can see WEP key + // Note : this is needed only for very old versions of WE + if (!capable(CAP_NET_ADMIN)) { + rc = -EPERM; break; } - local->spy_number = wrq->u.data.length; - if (local->spy_number > 0) { - struct sockaddr address[IW_MAX_SPY]; - int i; + char keybuf[MAX_KEY_SIZE]; + rc = airo_get_encode(dev, NULL, + &(wrq->u.encoding), keybuf); + if (wrq->u.encoding.pointer) { + if (copy_to_user(wrq->u.encoding.pointer, + keybuf, + wrq->u.encoding.length)) + rc = -EFAULT; + } + } + break; + + case SIOCGIWTXPOW: // Get the current Tx-Power + rc=airo_get_txpow(dev, NULL, &(wrq->u.txpower), NULL); + break; + case SIOCSIWTXPOW: + rc=airo_set_txpow(dev, NULL, &(wrq->u.txpower), NULL); + break; + + case SIOCSIWRETRY: + rc=airo_set_retry(dev, NULL, &(wrq->u.retry), NULL); + break; + case SIOCGIWRETRY: + rc=airo_get_retry(dev, NULL, &(wrq->u.retry), NULL); + break; - if (copy_from_user(address, wrq->u.data.pointer, - sizeof(struct sockaddr) * local->spy_number)) { + case SIOCGIWRANGE: // Get range of parameters + { + struct iw_range range; + rc = airo_get_range(dev, NULL, + &(wrq->u.data), (char *) &range); + if (copy_to_user(wrq->u.data.pointer, &range, + sizeof(struct iw_range))) rc = -EFAULT; - break; + } + break; + + case SIOCGIWPOWER: + rc=airo_get_power(dev, NULL, &(wrq->u.power), NULL); + break; + + case SIOCSIWPOWER: + rc=airo_set_power(dev, NULL, &(wrq->u.power), NULL); + break; + + case SIOCGIWSENS: + rc = airo_get_sens(dev, NULL, &(wrq->u.sens), NULL); + break; + + case SIOCSIWSENS: + rc = airo_set_sens(dev, NULL, &(wrq->u.sens), NULL); + break; + + case SIOCGIWAPLIST: + { + char buffer[IW_MAX_AP * (sizeof(struct sockaddr) + + sizeof(struct iw_quality))]; + if (wrq->u.data.pointer) { + rc = airo_get_aplist(dev, NULL, + &(wrq->u.data), buffer); + if (copy_to_user(wrq->u.data.pointer, + buffer, + (wrq->u.data.length * + (sizeof(struct sockaddr) + + sizeof(struct iw_quality))) + )) + rc = -EFAULT; } - for (i=0; ispy_number; i++) - memcpy(local->spy_address[i], address[i].sa_data, 6); - memset(local->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY); } break; - // Get the spy list - case SIOCGIWSPY: - wrq->u.data.length = local->spy_number; - if ((local->spy_number > 0) && (wrq->u.data.pointer)) +#ifdef WIRELESS_SPY + case SIOCSIWSPY: // Set the spy list { struct sockaddr address[IW_MAX_SPY]; - int i; - rc = verify_area(VERIFY_WRITE, wrq->u.data.pointer, (sizeof(struct iw_quality)+sizeof(struct sockaddr)) * IW_MAX_SPY); - if (rc) + /* Check the number of addresses */ + if (wrq->u.data.length > IW_MAX_SPY) { + rc = -E2BIG; break; - for (i=0; ispy_number; i++) - { - memcpy(address[i].sa_data, local->spy_address[i], 6); - address[i].sa_family = AF_UNIX; } - if (copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * local->spy_number)) { + /* Get the data in the driver */ + if (wrq->u.data.pointer) { + if (copy_from_user((char *) address, + wrq->u.data.pointer, + sizeof(struct sockaddr) * + wrq->u.data.length)) { rc = -EFAULT; break; - } - if (copy_to_user(wrq->u.data.pointer + (sizeof(struct sockaddr)*local->spy_number), local->spy_stat, sizeof(struct iw_quality) * local->spy_number)) { - rc = -EFAULT; + } + } else if (wrq->u.data.length != 0) { + rc = -EINVAL; break; } - for (i=0; ispy_number; i++) - local->spy_stat[i].updated = 0; + rc=airo_set_spy(dev, NULL, &(wrq->u.data), + (char *) address); + } + break; + + case SIOCGIWSPY: // Get the spy list + { + char buffer[IW_MAX_SPY * (sizeof(struct sockaddr) + + sizeof(struct iw_quality))]; + if (wrq->u.data.pointer) { + rc = airo_get_spy(dev, NULL, + &(wrq->u.data), buffer); + if (copy_to_user(wrq->u.data.pointer, + buffer, + (wrq->u.data.length * + (sizeof(struct sockaddr) + + sizeof(struct iw_quality))) + )) + rc = -EFAULT; + } } break; #endif /* WIRELESS_SPY */ #ifdef CISCO_EXT case SIOCGIWPRIV: - if(wrq->u.data.pointer) - { - struct iw_priv_args priv[] = - { /* cmd, set_args, get_args, name */ - { AIROIOCTL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl), IW_PRIV_TYPE_BYTE | 2047, "airoioctl" }, - { AIROIDIFC, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl), IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "airoidifc" }, - }; - + if(wrq->u.data.pointer) { /* Set the number of ioctl available */ - wrq->u.data.length = 2; + wrq->u.data.length = sizeof(airo_private_args) / sizeof( airo_private_args[0]); /* Copy structure to the user buffer */ - if(copy_to_user(wrq->u.data.pointer, (u_char *) priv, - sizeof(priv))) + if(copy_to_user(wrq->u.data.pointer, + (u_char *) airo_private_args, + sizeof(airo_private_args))) rc = -EFAULT; } break; #endif /* CISCO_EXT */ -#endif /* WIRELESS_EXT */ +#endif /* WIRELESS_EXT < 13 */ #ifdef CISCO_EXT case AIROIDIFC: @@ -4215,31 +5572,16 @@ rc = -EOPNOTSUPP; } -#ifdef WIRELESS_EXT +#if defined(WIRELESS_EXT) && WIRELESS_EXT < 13 + /* WE 13 and higher will use airo_config_commit */ /* Some of the "SET" function may have modified some of the * parameters. It's now time to commit them in the card */ - if(local->need_commit) { - /* A classical optimisation here is to not commit any change - * if the card is not "opened". This is what we do in - * wvlan_cs (see for details). - * For that, we would need to have the config RID saved in - * the airo_info struct and make sure to not re-read it if - * local->need_commit != 0. Then, you need to patch "open" - * to do the final commit of all parameters... - * Jean II */ - Resp rsp; - - disable_MAC(local); - local->config = config; /* ???? config is local !!! */ - checkThrottle(&config); - writeConfigRid(local, &config); - enable_MAC(local, &rsp); - - local->need_commit = 0; - } -#endif /* WIRELESS_EXT */ + airo_config_commit(dev, NULL, NULL, NULL); + if (rc == -EINPROGRESS) + return 0; +#endif /* WIRELESS_EXT < 13 */ - return(rc); + return rc; } #ifdef WIRELESS_EXT @@ -4255,7 +5597,7 @@ */ struct iw_statistics *airo_get_wireless_stats(struct net_device *dev) { - struct airo_info *local = (struct airo_info*) dev->priv; + struct airo_info *local = dev->priv; StatusRid status_rid; StatsRid stats_rid; u32 *vals = stats_rid.vals; @@ -4280,15 +5622,11 @@ * specific problems */ local->wstats.discard.nwid = vals[56] + vals[57] + vals[58];/* SSID Mismatch */ local->wstats.discard.code = vals[6];/* RxWepErr */ -#if WIRELESS_EXT > 11 local->wstats.discard.fragment = vals[30]; local->wstats.discard.retries = vals[10]; local->wstats.discard.misc = vals[1] + vals[32]; local->wstats.miss.beacon = vals[34]; -#else /* WIRELESS_EXT > 11 */ - local->wstats.discard.misc = vals[1] + vals[30] + vals[32]; -#endif /* WIRELESS_EXT > 11 */ - return (&local->wstats); + return &local->wstats; } #endif /* WIRELESS_EXT */ @@ -4307,6 +5645,8 @@ { case AIROGCAP: ridcode = RID_CAPABILITIES; break; case AIROGCFG: ridcode = RID_CONFIG; break; + case AIROPCFG: writeConfigRid ((struct airo_info *)dev->priv); + ridcode = RID_CONFIG; break; case AIROGSLIST: ridcode = RID_SSID; break; case AIROGVLIST: ridcode = RID_APLIST; break; case AIROGDRVNAM: ridcode = RID_DRVNAME; break; @@ -4363,7 +5703,8 @@ case AIROPSIDS: ridcode = RID_SSID; break; case AIROPCAP: ridcode = RID_CAPABILITIES; break; case AIROPAPLIST: ridcode = RID_APLIST; break; - case AIROPCFG: ridcode = RID_CONFIG; break; + case AIROPCFG: ((struct airo_info *)dev->priv)->config.len = 0; + ridcode = RID_CONFIG; break; case AIROPWEPKEYNV: ridcode = RID_WEP_PERM; break; case AIROPLEAPUSR: ridcode = RID_LEAPUSERNAME; break; case AIROPLEAPPWD: ridcode = RID_LEAPPASSWORD; break; @@ -4515,8 +5856,14 @@ int setflashmode (struct airo_info *ai) { OUT4500(ai, SWS0, FLASH_COMMAND); OUT4500(ai, SWS1, FLASH_COMMAND); - OUT4500(ai, SWS0, FLASH_COMMAND); - OUT4500(ai, COMMAND,0x10); + if (probe) { + OUT4500(ai, SWS0, FLASH_COMMAND); + OUT4500(ai, COMMAND,0x10); + } else { + OUT4500(ai, SWS2, FLASH_COMMAND); + OUT4500(ai, SWS3, FLASH_COMMAND); + OUT4500(ai, COMMAND,0); + } set_current_state (TASK_UNINTERRUPTIBLE); schedule_timeout (HZ/2); /* 500ms delay */ @@ -4626,10 +5973,10 @@ set_current_state (TASK_UNINTERRUPTIBLE); schedule_timeout (HZ); /* Added 12/7/00 */ - status = setup_card(ai, dev->dev_addr,&((struct airo_info*)dev->priv)->config); + status = setup_card(ai, dev->dev_addr); for( i = 0; i < MAX_FIDS; i++ ) { - ai->fids[i] = transmit_allocate( ai, 2312 ); + ai->fids[i] = transmit_allocate( ai, 2312, i >= MAX_FIDS / 2 ); } set_current_state (TASK_UNINTERRUPTIBLE); diff -Nru a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c --- a/drivers/pci/hotplug.c Sun Jun 2 18:44:58 2002 +++ b/drivers/pci/hotplug.c Sun Jun 2 18:44:58 2002 @@ -2,8 +2,6 @@ #include #include /* for hotplug_path */ -extern int pci_announce_device(struct pci_driver *drv, struct pci_dev *dev); - #ifndef FALSE #define FALSE (0) #define TRUE (!FALSE) @@ -49,28 +47,6 @@ } /** - * pci_announce_device_to_drivers - tell the drivers a new device has appeared - * @dev: the device that has shown up - * - * Notifys the drivers that a new device has appeared, and also notifys - * userspace through /sbin/hotplug. - */ -void -pci_announce_device_to_drivers(struct pci_dev *dev) -{ - struct list_head *ln; - - for(ln=pci_bus_type.drivers.next; ln != &pci_bus_type.drivers; ln=ln->next) { - struct pci_driver *drv = list_entry(ln, struct pci_driver, node); - if (drv->remove && pci_announce_device(drv, dev)) - break; - } - - /* notify userspace of new hotplug device */ - run_sbin_hotplug(dev, TRUE); -} - -/** * pci_insert_device - insert a hotplug device * @dev: the device to insert * @bus: where to insert it @@ -85,7 +61,8 @@ #ifdef CONFIG_PROC_FS pci_proc_attach_device(dev); #endif - pci_announce_device_to_drivers(dev); + /* notify userspace of new hotplug device */ + run_sbin_hotplug(dev, TRUE); } static void @@ -110,11 +87,7 @@ void pci_remove_device(struct pci_dev *dev) { - if (dev->driver) { - if (dev->driver->remove) - dev->driver->remove(dev); - dev->driver = NULL; - } + put_device(&dev->dev); list_del(&dev->bus_list); list_del(&dev->global_list); pci_free_resources(dev); @@ -128,4 +101,3 @@ EXPORT_SYMBOL(pci_insert_device); EXPORT_SYMBOL(pci_remove_device); -EXPORT_SYMBOL(pci_announce_device_to_drivers); diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c --- a/drivers/pci/pci-driver.c Sun Jun 2 18:44:58 2002 +++ b/drivers/pci/pci-driver.c Sun Jun 2 18:44:58 2002 @@ -5,6 +5,7 @@ #include #include +#include /* * Registration of PCI drivers and handling of hot-pluggable devices. @@ -34,32 +35,6 @@ return NULL; } -int -pci_announce_device(struct pci_driver *drv, struct pci_dev *dev) -{ - const struct pci_device_id *id; - int ret = 0; - - if (drv->id_table) { - id = pci_match_device(drv->id_table, dev); - if (!id) { - ret = 0; - goto out; - } - } else - id = NULL; - - dev_probe_lock(); - if (drv->probe(dev, id) >= 0) { - dev->driver = drv; - ret = 1; - } - dev_probe_unlock(); -out: - return ret; -} - - static int pci_device_probe(struct device * dev) { int error = 0; @@ -68,12 +43,11 @@ struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev); if (drv->probe) - error = drv->probe(pci_dev,NULL); - printk("%s: returning %d\n",__FUNCTION__,error); + error = drv->probe(pci_dev,drv->id_table); return error > 0 ? 0 : -ENODEV; } -static int pci_device_remove(struct device * dev, u32 flags) +static int pci_device_remove(struct device * dev) { struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev); @@ -123,7 +97,6 @@ pci_register_driver(struct pci_driver *drv) { int count = 0; - struct pci_dev * dev; /* initialize common driver fields */ drv->driver.name = drv->name; @@ -135,11 +108,6 @@ /* register with core */ count = driver_register(&drv->driver); - - pci_for_each_dev(dev) { - if (!pci_dev_driver(dev)) - pci_announce_device(drv, dev); - } return count ? count : 1; } @@ -156,20 +124,6 @@ void pci_unregister_driver(struct pci_driver *drv) { - list_t * node; - - node = drv->driver.devices.next; - - while (node != &drv->driver.devices) { - struct device * dev = list_entry(node,struct device,driver_list); - struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev); - - if (drv->remove) - drv->remove(pci_dev); - pci_dev->driver = NULL; - dev->driver = NULL; - list_del_init(&dev->driver_list); - } put_driver(&drv->driver); } @@ -198,8 +152,39 @@ return NULL; } +/** + * pci_bus_bind - Tell if a PCI device structure has a matching PCI device id structure + * @ids: array of PCI device id structures to search in + * @dev: the PCI device structure to match against + * + * Used by a driver to check whether a PCI device present in the + * system is in its list of supported devices.Returns the matching + * pci_device_id structure or %NULL if there is no match. + */ +static int pci_bus_bind(struct device * dev, struct device_driver * drv) +{ + struct pci_dev * pci_dev = list_entry(dev, struct pci_dev, dev); + struct pci_driver * pci_drv = list_entry(drv,struct pci_driver,driver); + const struct pci_device_id * ids = pci_drv->id_table; + + if (!ids) + return 0; + + while (ids->vendor || ids->subvendor || ids->class_mask) { + if ((ids->vendor == PCI_ANY_ID || ids->vendor == pci_dev->vendor) && + (ids->device == PCI_ANY_ID || ids->device == pci_dev->device) && + (ids->subvendor == PCI_ANY_ID || ids->subvendor == pci_dev->subsystem_vendor) && + (ids->subdevice == PCI_ANY_ID || ids->subdevice == pci_dev->subsystem_device) && + !((ids->class ^ pci_dev->class) & ids->class_mask)) + return 1; + ids++; + } + return 0; +} + struct bus_type pci_bus_type = { name: "pci", + bind: pci_bus_bind, }; static int __init pci_driver_init(void) diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c --- a/drivers/s390/block/xpram.c Sun Jun 2 18:44:58 2002 +++ b/drivers/s390/block/xpram.c Sun Jun 2 18:44:58 2002 @@ -59,25 +59,15 @@ #include #ifdef MODULE -char kernel_version [] = UTS_RELEASE; +char kernel_version [] = UTS_RELEASE; #endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98)) -# define XPRAM_VERSION 24 -#else -# define XPRAM_VERSION 22 -#endif - -#if (XPRAM_VERSION == 24) -# include -# include -#endif /* V24 */ +#include +#include #include #include /* printk() */ #include /* kmalloc() */ -#if (XPRAM_VERSION == 24) -# include -#endif /* V24 */ +#include #include /* everything... */ #include /* error codes */ #include @@ -89,7 +79,6 @@ #include /* cli(), *_flags */ #include /* put_user */ -#if (XPRAM_VERSION == 24) #define MAJOR_NR xpram_major /* force definitions on in blk.h */ int xpram_major; /* must be declared before including blk.h */ devfs_handle_t xpram_devfs_handle; @@ -105,7 +94,6 @@ #include "xpram.h" /* local definitions */ __setup("xpram_parts=", xpram_setup); -#endif /* V24 */ /* define the debug levels: @@ -133,26 +121,7 @@ #define PRINT_WARN(x...) printk ( KERN_DEBUG PRINTK_HEADER "warning:" x ) #define PRINT_ERR(x...) printk ( KERN_DEBUG PRINTK_HEADER "error:" x ) #define PRINT_FATAL(x...) printk ( KERN_DEBUG PRINTK_HEADER "panic:" x ) -#endif - -#if (XPRAM_VERSION == 22) -#define MAJOR_NR xpram_major /* force definitions on in blk.h */ -int xpram_major; /* must be declared before including blk.h */ - -#define DEVICE_NR(device) MINOR(device) /* xpram has no partition bits */ -#define DEVICE_NAME "xpram" /* name for messaging */ -#define DEVICE_INTR xpram_intrptr /* pointer to the bottom half */ -#define DEVICE_NO_RANDOM /* no entropy to contribute */ - - -#define DEVICE_OFF(d) /* do-nothing */ - -#define DEVICE_REQUEST *xpram_dummy_device_request /* dummy function variable - * to prevent warnings - */#include - -#include "xpram.h" /* local definitions */ -#endif /* V22 */ +#endif /* * Non-prefixed symbols are static. They are meant to be assigned at @@ -659,13 +628,6 @@ case BLKRRPART: /* re-read partition table: can't do it, 0x1259 */ return -EINVAL; -#if (XPRAM_VERSION == 22) - RO_IOCTLS(inode->i_rdev, arg); /* the default RO operations - * BLKROSET - * BLKROGET - */ -#endif /* V22 */ - case HDIO_GETGEO: /* * get geometry: we have to fake one... trim the size to a @@ -695,27 +657,6 @@ /* * The file operations */ - -#if (XPRAM_VERSION == 22) -struct file_operations xpram_fops = { - NULL, /* lseek: default */ - block_read, - block_write, - NULL, /* xpram_readdir */ - NULL, /* xpram_select */ - xpram_ioctl, - NULL, /* xpram_mmap */ - xpram_open, - NULL, /* flush */ - xpram_release, - block_fsync, - NULL, /* xpram_fasync */ - NULL, - NULL -}; -#endif /* V22 */ - -#if (XPRAM_VERSION == 24) struct block_device_operations xpram_devops = { owner: THIS_MODULE, @@ -723,7 +664,6 @@ open: xpram_open, release: xpram_release, }; -#endif /* V24 */ /* * Block-driver specific functions @@ -740,11 +680,7 @@ char * buffer; /* local pointer into buffer cache */ int dev_no; /* device number of request */ int fault; /* faulty access to expanded memory */ -#if ( XPRAM_VERSION == 24 ) struct request * current_req; /* working request */ -#else -# define current_req CURRENT -#endif /* V24 */ while(1) { if (blk_queue_empty(QUEUE)) { @@ -753,10 +689,8 @@ } fault=0; -#if ( XPRAM_VERSION == 24 ) current_req = CURRENT; -#endif /* V24 */ - dev_no = DEVICE_NR(current_req->rq_dev); + dev_no = DEVICE_NR(current_req->rq_dev); /* Check if the minor number is in range */ if ( dev_no > xpram_devs ) { static int count = 0; @@ -872,26 +806,18 @@ * partition size (if provided). A parsing error of a value * results in this value being set to -EINVAL. */ -#if (XPRAM_VERSION == 22) -void xpram_setup (char *str, int *ints) -#else int xpram_setup (char *str) -#endif /* V22 */ { devs = xpram_read_int(&str); - if ( devs != -EINVAL ) - if ( xpram_read_size_list_tail(&str,devs,sizes) < 0 ) { + if ( devs != -EINVAL ) + if ( xpram_read_size_list_tail(&str,devs,sizes) < 0 ) { PRINT_ERR("error while reading xpram parameters.\n"); -#if (XPRAM_VERSION == 24) return -EINVAL; -#endif /* V24 */ - } -#if (XPRAM_VERSION == 24) - else return 0; - else return -EINVAL; -#elif (XPRAM_VERSION == 22) - return; -#endif /* V24/V22 */ + } + else + return 0; + else + return -EINVAL; } /* @@ -911,12 +837,10 @@ int mem_auto_no=0; /* number of (implicit) zero parameters in sizes */ int mem_auto; /* automatically determined device size */ -#if (XPRAM_VERSION == 24) int minor_length; /* store the length of a minor (w/o '\0') */ int minor_thresh; /* threshhold for minor lenght */ request_queue_t *q; /* request queue */ -#endif /* V24 */ /* * Copy the (static) cfg variables to public prefixed ones to allow @@ -975,29 +899,23 @@ /* * Register your major, and accept a dynamic number */ -#if (XPRAM_VERSION == 22) - result = register_blkdev(xpram_major, "xpram", &xpram_fops); -#elif (XPRAM_VERSION == 24) result = devfs_register_blkdev(xpram_major, "xpram", &xpram_devops); -#endif /* V22/V24 */ if (result < 0) { PRINT_ERR("Can't get major %d\n",xpram_major); PRINT_ERR("Giving up xpram\n"); return result; } -#if (XPRAM_VERSION == 24) xpram_devfs_handle = devfs_mk_dir (NULL, "slram", NULL); devfs_register_series (xpram_devfs_handle, "%u", XPRAM_MAX_DEVS, DEVFS_FL_DEFAULT, XPRAM_MAJOR, 0, S_IFBLK | S_IRUSR | S_IWUSR, &xpram_devops, NULL); -#endif /* V22/V24 */ if (xpram_major == 0) xpram_major = result; /* dynamic */ major = xpram_major; /* Use `major' later on to save typing */ result = -ENOMEM; /* for the possible errors */ - /* + /* * measure expanded memory */ @@ -1018,13 +936,9 @@ * arrays if it uses the default values. */ -#if (XPRAM_VERSION == 22) - blk_dev[major].request_fn = xpram_request; -#elif (XPRAM_VERSION == 24) - q = BLK_DEFAULT_QUEUE (major); + q = BLK_DEFAULT_QUEUE(major); blk_init_queue (q, xpram_request); blk_queue_hardsect_size(q, xpram_hardsect); -#endif /* V22/V24 */ /* we want to have XPRAM_UNUSED blocks security buffer between devices */ mem_usable=xpram_mem_avail-(XPRAM_UNUSED*(xpram_devs-1)); @@ -1076,15 +990,12 @@ goto fail_malloc_devices; } memset(xpram_devices, 0, xpram_devs * sizeof (Xpram_Dev)); -#if (XPRAM_VERSION == 24) minor_length = 1; minor_thresh = 10; -#endif /* V24 */ for (i=0; i < xpram_devs; i++) { /* data and usage remain zeroed */ xpram_devices[i].size = xpram_sizes[i]; /* size in kB not in bytes */ atomic_set(&(xpram_devices[i].usage),0); -#if (XPRAM_VERSION == 24) if (i == minor_thresh) { minor_length++; minor_thresh *= 10; @@ -1119,27 +1030,20 @@ goto fail_devfs_register; } #endif /* WHY? */ -#endif /* V24 */ - } return 0; /* succeed */ /* clean up memory in case of failures */ -#if (XPRAM_VERSION == 24) fail_devfs_register: for (i=0; i < xpram_devs; i++) { if ( xpram_devices[i].device_name ) kfree(xpram_devices[i].device_name); } kfree(xpram_devices); -#endif /* V24 */ kfree (xpram_offsets); fail_malloc_devices: fail_malloc: -#if (XPRAM_VERSION == 22) - blk_dev[major].request_fn = NULL; -#endif /* V22 */ /* ??? unregister_chrdev(major, "xpram"); */ unregister_blkdev(major, "xpram"); return result; @@ -1168,20 +1072,12 @@ int i; /* first of all, reset all the data structures */ - -#if (XPRAM_VERSION == 22) - blk_dev[major].request_fn = NULL; -#endif /* V22 */ kfree(xpram_offsets); blk_clear(major); /* finally, the usual cleanup */ -#if (XPRAM_VERSION == 22) - unregister_blkdev(major, "xpram"); -#elif (XPRAM_VERSION == 24) devfs_unregister(xpram_devfs_handle); if (devfs_unregister_blkdev(MAJOR_NR, "xpram")) printk(KERN_WARNING "xpram: cannot unregister blkdev\n"); -#endif /* V22/V24 */ kfree(xpram_devices); } diff -Nru a/drivers/s390/misc/chandev.c b/drivers/s390/misc/chandev.c --- a/drivers/s390/misc/chandev.c Sun Jun 2 18:44:57 2002 +++ b/drivers/s390/misc/chandev.c Sun Jun 2 18:44:57 2002 @@ -3151,7 +3151,7 @@ buff=vmalloc(count+1); if(buff) { - rc = copy_from_user(buff,buffer,count); + rc = copy_from_user(buff,buffer,count) ? -EFAULT : 0; if (rc) goto chandev_write_exit; chandev_do_setup(FALSE,buff,count); diff -Nru a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c --- a/drivers/sbus/char/openprom.c Sun Jun 2 18:44:58 2002 +++ b/drivers/sbus/char/openprom.c Sun Jun 2 18:44:58 2002 @@ -408,9 +408,9 @@ tmp[len] = '\0'; - error = __copy_to_user((void *)arg, &op, sizeof(op)); - if (!error) - error = copy_to_user(op.op_buf, tmp, len); + if (__copy_to_user((void *)arg, &op, sizeof(op)) != 0 + || copy_to_user(op.op_buf, tmp, len) != 0) + error = -EFAULT; kfree(tmp); kfree(str); diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c --- a/drivers/scsi/ide-scsi.c Sun Jun 2 18:44:56 2002 +++ b/drivers/scsi/ide-scsi.c Sun Jun 2 18:44:56 2002 @@ -1,9 +1,6 @@ /* - * linux/drivers/scsi/ide-scsi.c Version 0.9 Jul 4, 1999 - * * Copyright (C) 1996 - 1999 Gadi Oxman */ - /* * Emulation of a SCSI host adapter for IDE ATAPI devices. * @@ -48,19 +45,17 @@ #include #include +#include + #include "scsi.h" #include "hosts.h" #include "sd.h" -#include - -#define IDESCSI_DEBUG_LOG 0 -/* - * Packet command status bits. +/* FIXME: Right now we always register a single scsi host for every single + * device. We should be just registering a single scsi host per ATA host chip + * and deal properly with channels! The reentrancy efforts are therefore not + * quite right done now. */ -#define PC_DMA_IN_PROGRESS 0 /* 1 while DMA in progress */ -#define PC_WRITING 1 /* Data direction */ -#define PC_TRANSFORM 2 /* transform SCSI commands */ /* * SCSI command transformation layer @@ -213,7 +208,7 @@ kfree(atapi_buf); } -static inline void idescsi_free_bio (struct bio *bio) +static inline void idescsi_free_bio(struct bio *bio) { struct bio *bhp; @@ -234,15 +229,10 @@ printk("]\n"); } -static inline idescsi_scsi_t *idescsi_private(struct Scsi_Host *host) -{ - return (idescsi_scsi_t*) &host[1]; -} - static int idescsi_end_request(struct ata_device *drive, struct request *rq, int uptodate) { struct Scsi_Host *host = drive->driver_data; - idescsi_scsi_t *scsi = idescsi_private(host); + idescsi_scsi_t *scsi = (idescsi_scsi_t *) host->hostdata[0]; struct atapi_packet_command *pc = (struct atapi_packet_command *) rq->special; int log = test_bit(IDESCSI_LOG_CMD, &scsi->log); u8 *scsi_buf; @@ -252,7 +242,11 @@ ide_end_request(drive, rq, uptodate); return 0; } - ide_end_drive_cmd(drive, rq, 0, 0); + + blkdev_dequeue_request(rq); + drive->rq = NULL; + end_that_request_last(rq); + if (rq->errors >= ERROR_MAX) { pc->s.scsi_cmd->result = DID_ERROR << 16; if (log) @@ -277,7 +271,7 @@ spin_lock_irqsave(host->host_lock, flags); pc->s.done(pc->s.scsi_cmd); spin_unlock_irqrestore(host->host_lock, flags); - idescsi_free_bio (rq->bio); + idescsi_free_bio(rq->bio); kfree(pc); kfree(rq); scsi->pc = NULL; @@ -295,31 +289,30 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request *rq) { struct Scsi_Host *host = drive->driver_data; - idescsi_scsi_t *scsi = idescsi_private(host); - byte status, ireason; + idescsi_scsi_t *scsi = (idescsi_scsi_t *) host->hostdata[0]; + u8 ireason; int bcount; struct atapi_packet_command *pc=scsi->pc; unsigned int temp; -#if IDESCSI_DEBUG_LOG +#ifdef DEBUG printk (KERN_INFO "ide-scsi: Reached idescsi_pc_intr interrupt handler\n"); -#endif /* IDESCSI_DEBUG_LOG */ +#endif if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { -#if IDESCSI_DEBUG_LOG +#ifdef DEBUG printk ("ide-scsi: %s: DMA complete\n", drive->name); -#endif /* IDESCSI_DEBUG_LOG */ +#endif pc->actually_transferred=pc->request_transfer; udma_stop(drive); } - status = GET_STAT(); /* Clear the interrupt */ - - if ((status & DRQ_STAT) == 0) { /* No more interrupts */ + /* Clear the interrupt */ + if (ata_status(drive, 0, DRQ_STAT)) { /* No more interrupts */ if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred); ide__sti(); - if (status & ERR_STAT) + if (drive->status & ERR_STAT) rq->errors++; idescsi_end_request(drive, rq, 1); return ide_stopped; @@ -351,7 +344,7 @@ ide_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); return ide_started; } -#if IDESCSI_DEBUG_LOG +#ifdef DEBUG printk (KERN_NOTICE "ide-scsi: The scsi wants to send us more data than expected - allowing transfer\n"); #endif } @@ -379,7 +372,7 @@ static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct request *rq) { struct Scsi_Host *host = drive->driver_data; - idescsi_scsi_t *scsi = idescsi_private(host); + idescsi_scsi_t *scsi = (idescsi_scsi_t *) host->hostdata[0]; struct atapi_packet_command *pc = scsi->pc; byte ireason; ide_startstop_t startstop; @@ -405,7 +398,7 @@ struct atapi_packet_command *pc) { struct Scsi_Host *host = drive->driver_data; - idescsi_scsi_t *scsi = idescsi_private(host); + idescsi_scsi_t *scsi = (idescsi_scsi_t *) host->hostdata[0]; int bcount; int dma_ok = 0; @@ -414,19 +407,14 @@ pc->current_position=pc->buffer; bcount = min(pc->request_transfer, 63 * 1024); /* Request to transfer the entire buffer at once */ - if (drive->using_dma && rq->bio) { - if (test_bit (PC_WRITING, &pc->flags)) - dma_ok = !udma_write(drive, rq); - else - dma_ok = !udma_read(drive, rq); - } + if (drive->using_dma && rq->bio) + dma_ok = !udma_init(drive, rq); - SELECT_DRIVE(drive->channel, drive); - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl,IDE_CONTROL_REG); - OUT_BYTE (dma_ok,IDE_FEATURE_REG); - OUT_BYTE (bcount >> 8,IDE_BCOUNTH_REG); - OUT_BYTE (bcount & 0xff,IDE_BCOUNTL_REG); + ata_select(drive, 10); + ata_irq_enable(drive, 1); + OUT_BYTE(dma_ok,IDE_FEATURE_REG); + OUT_BYTE(bcount >> 8,IDE_BCOUNTH_REG); + OUT_BYTE(bcount & 0xff,IDE_BCOUNTL_REG); if (dma_ok) { set_bit(PC_DMA_IN_PROGRESS, &pc->flags); @@ -447,9 +435,16 @@ */ static ide_startstop_t idescsi_do_request(struct ata_device *drive, struct request *rq, sector_t block) { -#if IDESCSI_DEBUG_LOG - printk (KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors); - printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); +#ifdef DEBUG + printk(KERN_INFO "rq_status: %d, cmd: %d, errors: %d\n", + rq->rq_status, + (unsigned int) + rq->cmd, + rq->errors); + printk(KERN_INFO "sector: %lu, nr_sectors: %lu, current_nr_sectors: %lu\n", + rq->sector, + rq->nr_sectors, + rq->current_nr_sectors); #endif if (rq->flags & REQ_SPECIAL) { @@ -466,7 +461,7 @@ return 0; } -static void idescsi_ide_release(struct inode *inode, struct file *filp, struct ata_device *drive) +static void idescsi_release(struct inode *inode, struct file *filp, struct ata_device *drive) { MOD_DEC_USE_COUNT; } @@ -478,7 +473,9 @@ if (ide_unregister_subdriver (drive)) { return 1; } + kfree((idescsi_scsi_t *) host->hostdata[0]); scsi_unregister(host); + return 0; } @@ -493,34 +490,32 @@ /* * IDE subdriver functions, registered with ide.c */ -static struct ata_operations idescsi_driver = { +static struct ata_operations ata_ops = { owner: THIS_MODULE, attach: idescsi_attach, cleanup: idescsi_cleanup, - standby: NULL, do_request: idescsi_do_request, end_request: idescsi_end_request, - ioctl: NULL, open: idescsi_open, - release: idescsi_ide_release, - check_media_change: NULL, + release: idescsi_release, revalidate: idescsi_revalidate, - capacity: NULL, }; -int idescsi_detect (Scsi_Host_Template *host_template) +static int idescsi_detect(Scsi_Host_Template *host_template) { - return register_ata_driver(&idescsi_driver); + return register_ata_driver(&ata_ops); } -const char *idescsi_info (struct Scsi_Host *host) +static const char *idescsi_info(struct Scsi_Host *host) { - return "SCSI host adapter emulation for IDE ATAPI devices"; + static const char *msg = "SCSI host adapter emulation for ATAPI devices"; + + return msg; } -int idescsi_ioctl (Scsi_Device *dev, int cmd, void *arg) +static int idescsi_ioctl(Scsi_Device *dev, int cmd, void *arg) { - idescsi_scsi_t *scsi = idescsi_private(dev->host); + idescsi_scsi_t *scsi = (idescsi_scsi_t *) dev->host->hostdata[0]; if (cmd == SG_SET_TRANSFORM) { if (arg) @@ -530,10 +525,11 @@ return 0; } else if (cmd == SG_GET_TRANSFORM) return put_user(test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform), (int *) arg); + return -EINVAL; } -static inline struct bio *idescsi_kmalloc_bio (int count) +static inline struct bio *idescsi_kmalloc_bio(int count) { struct bio *bh, *bhp, *first_bh; @@ -552,7 +548,8 @@ } return first_bh; abort: - idescsi_free_bio (first_bh); + idescsi_free_bio(first_bh); + return NULL; } @@ -587,7 +584,7 @@ if (segments) { if ((first_bh = bh = idescsi_kmalloc_bio (segments)) == NULL) return NULL; -#if IDESCSI_DEBUG_LOG +#ifdef DEBUG printk ("ide-scsi: %s: building DMA table, %d segments, %dkB total\n", drive->name, segments, pc->request_transfer >> 10); #endif while (segments--) { @@ -601,7 +598,7 @@ } else { if ((first_bh = bh = idescsi_kmalloc_bio (1)) == NULL) return NULL; -#if IDESCSI_DEBUG_LOG +#ifdef DEBUG printk ("ide-scsi: %s: building DMA table for a single buffer (%dkB)\n", drive->name, pc->request_transfer >> 10); #endif bh->bi_io_vec[0].bv_page = virt_to_page(pc->s.scsi_cmd->request_buffer); @@ -615,16 +612,16 @@ static inline int should_transform(struct ata_device *drive, Scsi_Cmnd *cmd) { struct Scsi_Host *host = drive->driver_data; - idescsi_scsi_t *scsi = idescsi_private(host); + idescsi_scsi_t *scsi = (idescsi_scsi_t *) host->hostdata[0]; if (major(cmd->request.rq_dev) == SCSI_GENERIC_MAJOR) return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); return test_bit(IDESCSI_TRANSFORM, &scsi->transform); } -int idescsi_queue (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) +static int idescsi_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) { - idescsi_scsi_t *scsi = idescsi_private(cmd->host); + idescsi_scsi_t *scsi = (idescsi_scsi_t *) cmd->host->hostdata[0]; struct ata_device *drive = scsi->drive; struct request *rq = NULL; struct atapi_packet_command *pc = NULL; @@ -665,17 +662,20 @@ } } - ide_init_drive_cmd (rq); + memset(rq, 0, sizeof(*rq)); + rq->flags = REQ_SPECIAL; rq->special = (char *) pc; rq->bio = idescsi_dma_bio (drive, pc); - rq->flags = REQ_SPECIAL; spin_unlock_irq(cmd->host->host_lock); - (void) ide_do_drive_cmd (drive, rq, ide_end); + ide_do_drive_cmd (drive, rq, ide_end); spin_lock_irq(cmd->host->host_lock); + return 0; abort: - if (pc) kfree (pc); - if (rq) kfree (rq); + if (pc) + kfree (pc); + if (rq) + kfree (rq); cmd->result = DID_ERROR << 16; done(cmd); @@ -684,14 +684,14 @@ /* FIXME: This needs further investigation. */ -int idescsi_device_reset (Scsi_Cmnd *cmd) +static int idescsi_device_reset(Scsi_Cmnd *cmd) { return SUCCESS; } -int idescsi_bios (Disk *disk, kdev_t dev, int *parm) +static int idescsi_bios(Disk *disk, kdev_t dev, int *parm) { - idescsi_scsi_t *scsi = idescsi_private(disk->device->host); + idescsi_scsi_t *scsi = (idescsi_scsi_t *) disk->device->host->hostdata[0]; struct ata_device *drive = scsi->drive; if (drive->bios_cyl && drive->bios_head && drive->bios_sect) { @@ -702,7 +702,7 @@ return 0; } -static Scsi_Host_Template idescsi_template = { +static Scsi_Host_Template template = { module: THIS_MODULE, name: "idescsi", detect: idescsi_detect, @@ -713,7 +713,7 @@ info: idescsi_info, ioctl: idescsi_ioctl, queuecommand: idescsi_queue, - eh_device_reset_handler: + eh_device_reset_handler: idescsi_device_reset, bios_param: idescsi_bios, can_queue: 10, @@ -722,7 +722,8 @@ cmd_per_lun: 5, use_clustering: DISABLE_CLUSTERING, emulated: 1, - proc_name: "ide-scsi", + /* FIXME: Buggy generic SCSI code doesn't remove /proc/entires! */ + proc_name: "atapi" }; /* @@ -737,9 +738,8 @@ if (drive->type == ATA_DISK) return; - host = scsi_register(&idescsi_template, sizeof(idescsi_scsi_t)); - - if(host == NULL) { + host = scsi_register(&template, sizeof(idescsi_scsi_t)); + if (!host) { printk (KERN_ERR "ide-scsi: %s: Can't allocate a scsi host structure\n", drive->name); @@ -747,8 +747,9 @@ } host->max_lun = drive->last_lun + 1; + host->max_id = 1; - if (ide_register_subdriver (drive, &idescsi_driver)) { + if (ide_register_subdriver(drive, &ata_ops)) { printk (KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name); scsi_unregister(host); return; @@ -757,28 +758,29 @@ drive->driver_data = host; drive->ready_stat = 0; - scsi = idescsi_private(host); - memset (scsi, 0, sizeof (idescsi_scsi_t)); + scsi = kmalloc(sizeof(*scsi), GFP_ATOMIC); + host->hostdata[0] = (unsigned long) scsi; + memset(scsi,0, sizeof (*scsi)); scsi->drive = drive; if (drive->id && (drive->id->config & 0x0060) == 0x20) set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags); set_bit(IDESCSI_TRANSFORM, &scsi->transform); clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); -#if IDESCSI_DEBUG_LOG +#ifdef DEBUG set_bit(IDESCSI_LOG_CMD, &scsi->log); #endif } static int __init init_idescsi_module(void) { - return scsi_register_host(&idescsi_template); + return scsi_register_host(&template); } static void __exit exit_idescsi_module(void) { - unregister_ata_driver(&idescsi_driver); - scsi_unregister_host(&idescsi_template); + unregister_ata_driver(&ata_ops); + scsi_unregister_host(&template); } module_init(init_idescsi_module); diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c --- a/drivers/scsi/qla1280.c Sun Jun 2 18:44:58 2002 +++ b/drivers/scsi/qla1280.c Sun Jun 2 18:44:58 2002 @@ -806,8 +806,8 @@ struct scsi_qla_host *ha; struct device_reg *reg; - printk("qla1x160: Initializing ISP12160 on PCI bus %i, dev %i\n", - pdev->bus->number, PCI_SLOT(pdev->devfn)); + printk("qla1x160: Initializing ISP12160 on PCI bus %i, dev %i, irq %i\n", + pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->irq); host = scsi_register(template, sizeof(struct scsi_qla_host)); if (!host) { diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c --- a/drivers/scsi/scsi_debug.c Sun Jun 2 18:44:58 2002 +++ b/drivers/scsi/scsi_debug.c Sun Jun 2 18:44:58 2002 @@ -34,7 +34,6 @@ #include #include -#include #include #include diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Sun Jun 2 18:44:58 2002 +++ b/drivers/scsi/scsi_scan.c Sun Jun 2 18:44:58 2002 @@ -25,16 +25,16 @@ /* * Flags for irregular SCSI devices that need special treatment */ -#define BLIST_NOLUN 0x001 /* Don't scan for LUNs */ -#define BLIST_FORCELUN 0x002 /* Known to have LUNs, force sanning */ -#define BLIST_BORKEN 0x004 /* Flag for broken handshaking */ -#define BLIST_KEY 0x008 /* Needs to be unlocked by special command */ -#define BLIST_SINGLELUN 0x010 /* LUNs should better not be used in parallel */ +#define BLIST_NOLUN 0x001 /* Don't scan for LUNs */ +#define BLIST_FORCELUN 0x002 /* Known to have LUNs, force sanning */ +#define BLIST_BORKEN 0x004 /* Flag for broken handshaking */ +#define BLIST_KEY 0x008 /* Needs to be unlocked by special command */ +#define BLIST_SINGLELUN 0x010 /* LUNs should better not be used in parallel */ #define BLIST_NOTQ 0x020 /* Buggy Tagged Command Queuing */ -#define BLIST_SPARSELUN 0x040 /* Non consecutive LUN numbering */ +#define BLIST_SPARSELUN 0x040 /* Non consecutive LUN numbering */ #define BLIST_MAX5LUN 0x080 /* Avoid LUNS >= 5 */ -#define BLIST_ISDISK 0x100 /* Treat as (removable) disk */ -#define BLIST_ISROM 0x200 /* Treat as (removable) CD-ROM */ +#define BLIST_ISDISK 0x100 /* Treat as (removable) disk */ +#define BLIST_ISROM 0x200 /* Treat as (removable) CD-ROM */ #define BLIST_LARGELUN 0x400 /* LUNs larger than 7 despite reporting as SCSI 2 */ #define BLIST_INQUIRY_36 0x800 /* override additional length field */ #define BLIST_INQUIRY_58 0x1000 /* ... for broken inquiry responses */ @@ -86,7 +86,7 @@ {"MAXTOR", "MXT-1240S", "I1.2", BLIST_NOLUN}, /* Locks up when LUN>0 polled */ {"MAXTOR", "XT-4170S", "B5A", BLIST_NOLUN}, /* Locks-up sometimes when LUN>0 polled. */ {"MAXTOR", "XT-8760S", "B7B", BLIST_NOLUN}, /* guess what? */ - {"MEDIAVIS", "RENO CD-ROMX2A", "2.03", BLIST_NOLUN}, /*Responds to all lun */ + {"MEDIAVIS", "RENO CD-ROMX2A", "2.03", BLIST_NOLUN}, /* Responds to all lun */ {"NEC", "CD-ROM DRIVE:841", "1.0", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */ {"PHILIPS", "PCA80SC", "V4-2", BLIST_NOLUN}, /* Responds to all lun */ {"RODIME", "RO3000S", "2.33", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ @@ -98,7 +98,7 @@ * SCSI code to reset bus.*/ {"SEAGATE", "ST296", "921", BLIST_NOLUN}, /* Responds to all lun */ {"SEAGATE", "ST1581", "6538", BLIST_NOLUN}, /* Responds to all lun */ - {"SONY", "CD-ROM CDU-541", "4.3d", BLIST_NOLUN}, + {"SONY", "CD-ROM CDU-541", "4.3d", BLIST_NOLUN}, {"SONY", "CD-ROM CDU-55S", "1.0i", BLIST_NOLUN}, {"SONY", "CD-ROM CDU-561", "1.7x", BLIST_NOLUN}, {"SONY", "CD-ROM CDU-8012", "*", BLIST_NOLUN}, @@ -120,8 +120,7 @@ {"HP", "C1790A", "", BLIST_NOLUN}, /* scanjet iip */ {"HP", "C2500A", "", BLIST_NOLUN}, /* scanjet iicx */ {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ - {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 - * extra reset */ + {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 extra reset */ {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ {"YAMAHA", "CRW6416S", "1.0c", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ {"MITSUMI", "CD-R CR-2201CS", "6119", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ @@ -453,7 +452,7 @@ else lun0_sl = find_lun0_scsi_level(channel, dev, shpnt); scan_scsis_single(channel, dev, lun, lun0_sl, &SDpnt, shpnt, - scsi_result); + scsi_result); if (SDpnt != oldSDpnt) { /* it could happen the blockdevice hasn't yet been inited */ diff -Nru a/drivers/usb/Config.in b/drivers/usb/Config.in --- a/drivers/usb/Config.in Sun Jun 2 18:44:57 2002 +++ b/drivers/usb/Config.in Sun Jun 2 18:44:57 2002 @@ -4,7 +4,13 @@ mainmenu_option next_comment comment 'USB support' -dep_tristate 'Support for USB' CONFIG_USB $CONFIG_PCI +# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. +if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SA1111" = "y" ]; then + tristate 'Support for USB' CONFIG_USB +else + define_bool CONFIG_USB n +fi + if [ "$CONFIG_USB" = "y" -o "$CONFIG_USB" = "m" ]; then source drivers/usb/core/Config.in diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile --- a/drivers/usb/Makefile Sun Jun 2 18:44:58 2002 +++ b/drivers/usb/Makefile Sun Jun 2 18:44:58 2002 @@ -6,9 +6,11 @@ mod-subdirs := serial obj-$(CONFIG_USB) += core/ + obj-$(CONFIG_USB_EHCI_HCD) += host/ obj-$(CONFIG_USB_OHCI_HCD) += host/ obj-$(CONFIG_USB_OHCI) += host/ +obj-$(CONFIG_USB_OHCI_SA1111) += host/ obj-$(CONFIG_USB_SL811HS) += host/ obj-$(CONFIG_USB_UHCI_ALT) += host/ obj-$(CONFIG_USB_UHCI_HCD_ALT) += host/ diff -Nru a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile --- a/drivers/usb/core/Makefile Sun Jun 2 18:44:58 2002 +++ b/drivers/usb/core/Makefile Sun Jun 2 18:44:58 2002 @@ -2,9 +2,10 @@ # Makefile for USB Core files and filesystem # -export-objs := usb.o hcd.o +export-objs := usb.o hcd.o urb.o message.o config.o -usbcore-objs := usb.o usb-debug.o hub.o hcd.o +usbcore-objs := usb.o usb-debug.o hub.o hcd.o urb.o message.o \ + config.o ifeq ($(CONFIG_USB_DEVICEFS),y) usbcore-objs += devio.o inode.o drivers.o devices.o diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/core/config.c Sun Jun 2 18:44:58 2002 @@ -0,0 +1,494 @@ +#include +#include +#include +#include +#include + +static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size) +{ + struct usb_descriptor_header *header; + unsigned char *begin; + int parsed = 0, len, numskipped; + + header = (struct usb_descriptor_header *)buffer; + + /* Everything should be fine being passed into here, but we sanity */ + /* check JIC */ + if (header->bLength > size) { + err("ran out of descriptors parsing"); + return -1; + } + + if (header->bDescriptorType != USB_DT_ENDPOINT) { + warn("unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X", + endpoint->bDescriptorType, USB_DT_ENDPOINT); + return parsed; + } + + if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) + memcpy(endpoint, buffer, USB_DT_ENDPOINT_AUDIO_SIZE); + else + memcpy(endpoint, buffer, USB_DT_ENDPOINT_SIZE); + + le16_to_cpus(&endpoint->wMaxPacketSize); + + buffer += header->bLength; + size -= header->bLength; + parsed += header->bLength; + + /* Skip over the rest of the Class Specific or Vendor Specific */ + /* descriptors */ + begin = buffer; + numskipped = 0; + while (size >= sizeof(struct usb_descriptor_header)) { + header = (struct usb_descriptor_header *)buffer; + + if (header->bLength < 2) { + err("invalid descriptor length of %d", header->bLength); + return -1; + } + + /* If we find another "proper" descriptor then we're done */ + if ((header->bDescriptorType == USB_DT_ENDPOINT) || + (header->bDescriptorType == USB_DT_INTERFACE) || + (header->bDescriptorType == USB_DT_CONFIG) || + (header->bDescriptorType == USB_DT_DEVICE)) + break; + + dbg("skipping descriptor 0x%X", + header->bDescriptorType); + numskipped++; + + buffer += header->bLength; + size -= header->bLength; + parsed += header->bLength; + } + if (numskipped) + dbg("skipped %d class/vendor specific endpoint descriptors", numskipped); + + /* Copy any unknown descriptors into a storage area for drivers */ + /* to later parse */ + len = (int)(buffer - begin); + if (!len) { + endpoint->extra = NULL; + endpoint->extralen = 0; + return parsed; + } + + endpoint->extra = kmalloc(len, GFP_KERNEL); + + if (!endpoint->extra) { + err("couldn't allocate memory for endpoint extra descriptors"); + endpoint->extralen = 0; + return parsed; + } + + memcpy(endpoint->extra, begin, len); + endpoint->extralen = len; + + return parsed; +} + +static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size) +{ + int i, len, numskipped, retval, parsed = 0; + struct usb_descriptor_header *header; + struct usb_interface_descriptor *ifp; + unsigned char *begin; + + interface->act_altsetting = 0; + interface->num_altsetting = 0; + interface->max_altsetting = USB_ALTSETTINGALLOC; + + interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL); + + if (!interface->altsetting) { + err("couldn't kmalloc interface->altsetting"); + return -1; + } + + while (size > 0) { + if (interface->num_altsetting >= interface->max_altsetting) { + void *ptr; + int oldmas; + + oldmas = interface->max_altsetting; + interface->max_altsetting += USB_ALTSETTINGALLOC; + if (interface->max_altsetting > USB_MAXALTSETTING) { + warn("too many alternate settings (max %d)", + USB_MAXALTSETTING); + return -1; + } + + ptr = interface->altsetting; + interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL); + if (!interface->altsetting) { + err("couldn't kmalloc interface->altsetting"); + interface->altsetting = ptr; + return -1; + } + memcpy(interface->altsetting, ptr, sizeof(struct usb_interface_descriptor) * oldmas); + + kfree(ptr); + } + + ifp = interface->altsetting + interface->num_altsetting; + ifp->endpoint = NULL; + ifp->extra = NULL; + ifp->extralen = 0; + interface->num_altsetting++; + + memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE); + + /* Skip over the interface */ + buffer += ifp->bLength; + parsed += ifp->bLength; + size -= ifp->bLength; + + begin = buffer; + numskipped = 0; + + /* Skip over any interface, class or vendor descriptors */ + while (size >= sizeof(struct usb_descriptor_header)) { + header = (struct usb_descriptor_header *)buffer; + + if (header->bLength < 2) { + err("invalid descriptor length of %d", header->bLength); + return -1; + } + + /* If we find another "proper" descriptor then we're done */ + if ((header->bDescriptorType == USB_DT_INTERFACE) || + (header->bDescriptorType == USB_DT_ENDPOINT) || + (header->bDescriptorType == USB_DT_CONFIG) || + (header->bDescriptorType == USB_DT_DEVICE)) + break; + + numskipped++; + + buffer += header->bLength; + parsed += header->bLength; + size -= header->bLength; + } + + if (numskipped) + dbg("skipped %d class/vendor specific interface descriptors", numskipped); + + /* Copy any unknown descriptors into a storage area for */ + /* drivers to later parse */ + len = (int)(buffer - begin); + if (len) { + ifp->extra = kmalloc(len, GFP_KERNEL); + + if (!ifp->extra) { + err("couldn't allocate memory for interface extra descriptors"); + ifp->extralen = 0; + return -1; + } + memcpy(ifp->extra, begin, len); + ifp->extralen = len; + } + + /* Did we hit an unexpected descriptor? */ + header = (struct usb_descriptor_header *)buffer; + if ((size >= sizeof(struct usb_descriptor_header)) && + ((header->bDescriptorType == USB_DT_CONFIG) || + (header->bDescriptorType == USB_DT_DEVICE))) + return parsed; + + if (ifp->bNumEndpoints > USB_MAXENDPOINTS) { + warn("too many endpoints"); + return -1; + } + + ifp->endpoint = (struct usb_endpoint_descriptor *) + kmalloc(ifp->bNumEndpoints * + sizeof(struct usb_endpoint_descriptor), GFP_KERNEL); + if (!ifp->endpoint) { + err("out of memory"); + return -1; + } + + memset(ifp->endpoint, 0, ifp->bNumEndpoints * + sizeof(struct usb_endpoint_descriptor)); + + for (i = 0; i < ifp->bNumEndpoints; i++) { + header = (struct usb_descriptor_header *)buffer; + + if (header->bLength > size) { + err("ran out of descriptors parsing"); + return -1; + } + + retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size); + if (retval < 0) + return retval; + + buffer += retval; + parsed += retval; + size -= retval; + } + + /* We check to see if it's an alternate to this one */ + ifp = (struct usb_interface_descriptor *)buffer; + if (size < USB_DT_INTERFACE_SIZE || + ifp->bDescriptorType != USB_DT_INTERFACE || + !ifp->bAlternateSetting) + return parsed; + } + + return parsed; +} + +int usb_parse_configuration(struct usb_config_descriptor *config, char *buffer) +{ + int i, retval, size; + struct usb_descriptor_header *header; + + memcpy(config, buffer, USB_DT_CONFIG_SIZE); + le16_to_cpus(&config->wTotalLength); + size = config->wTotalLength; + + if (config->bNumInterfaces > USB_MAXINTERFACES) { + warn("too many interfaces"); + return -1; + } + + config->interface = (struct usb_interface *) + kmalloc(config->bNumInterfaces * + sizeof(struct usb_interface), GFP_KERNEL); + dbg("kmalloc IF %p, numif %i", config->interface, config->bNumInterfaces); + if (!config->interface) { + err("out of memory"); + return -1; + } + + memset(config->interface, 0, + config->bNumInterfaces * sizeof(struct usb_interface)); + + buffer += config->bLength; + size -= config->bLength; + + config->extra = NULL; + config->extralen = 0; + + for (i = 0; i < config->bNumInterfaces; i++) { + int numskipped, len; + char *begin; + + /* Skip over the rest of the Class Specific or Vendor */ + /* Specific descriptors */ + begin = buffer; + numskipped = 0; + while (size >= sizeof(struct usb_descriptor_header)) { + header = (struct usb_descriptor_header *)buffer; + + if ((header->bLength > size) || (header->bLength < 2)) { + err("invalid descriptor length of %d", header->bLength); + return -1; + } + + /* If we find another "proper" descriptor then we're done */ + if ((header->bDescriptorType == USB_DT_ENDPOINT) || + (header->bDescriptorType == USB_DT_INTERFACE) || + (header->bDescriptorType == USB_DT_CONFIG) || + (header->bDescriptorType == USB_DT_DEVICE)) + break; + + dbg("skipping descriptor 0x%X", header->bDescriptorType); + numskipped++; + + buffer += header->bLength; + size -= header->bLength; + } + if (numskipped) + dbg("skipped %d class/vendor specific endpoint descriptors", numskipped); + + /* Copy any unknown descriptors into a storage area for */ + /* drivers to later parse */ + len = (int)(buffer - begin); + if (len) { + if (config->extralen) { + warn("extra config descriptor"); + } else { + config->extra = kmalloc(len, GFP_KERNEL); + if (!config->extra) { + err("couldn't allocate memory for config extra descriptors"); + config->extralen = 0; + return -1; + } + + memcpy(config->extra, begin, len); + config->extralen = len; + } + } + + retval = usb_parse_interface(config->interface + i, buffer, size); + if (retval < 0) + return retval; + + buffer += retval; + size -= retval; + } + + return size; +} + +// hub-only!! ... and only exported for reset/reinit path. +// otherwise used internally on disconnect/destroy path +void usb_destroy_configuration(struct usb_device *dev) +{ + int c, i, j, k; + + if (!dev->config) + return; + + if (dev->rawdescriptors) { + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) + kfree(dev->rawdescriptors[i]); + + kfree(dev->rawdescriptors); + } + + for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { + struct usb_config_descriptor *cf = &dev->config[c]; + + if (!cf->interface) + break; + + for (i = 0; i < cf->bNumInterfaces; i++) { + struct usb_interface *ifp = + &cf->interface[i]; + + if (!ifp->altsetting) + break; + + for (j = 0; j < ifp->num_altsetting; j++) { + struct usb_interface_descriptor *as = + &ifp->altsetting[j]; + + if(as->extra) { + kfree(as->extra); + } + + if (!as->endpoint) + break; + + for(k = 0; k < as->bNumEndpoints; k++) { + if(as->endpoint[k].extra) { + kfree(as->endpoint[k].extra); + } + } + kfree(as->endpoint); + } + + kfree(ifp->altsetting); + } + kfree(cf->interface); + } + kfree(dev->config); +} + + +// hub-only!! ... and only in reset path, or usb_new_device() +// (used by real hubs and virtual root hubs) +int usb_get_configuration(struct usb_device *dev) +{ + int result; + unsigned int cfgno, length; + unsigned char *buffer; + unsigned char *bigbuffer; + struct usb_config_descriptor *desc; + + if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { + warn("too many configurations"); + return -EINVAL; + } + + if (dev->descriptor.bNumConfigurations < 1) { + warn("not enough configurations"); + return -EINVAL; + } + + dev->config = (struct usb_config_descriptor *) + kmalloc(dev->descriptor.bNumConfigurations * + sizeof(struct usb_config_descriptor), GFP_KERNEL); + if (!dev->config) { + err("out of memory"); + return -ENOMEM; + } + memset(dev->config, 0, dev->descriptor.bNumConfigurations * + sizeof(struct usb_config_descriptor)); + + dev->rawdescriptors = (char **)kmalloc(sizeof(char *) * + dev->descriptor.bNumConfigurations, GFP_KERNEL); + if (!dev->rawdescriptors) { + err("out of memory"); + return -ENOMEM; + } + + buffer = kmalloc(8, GFP_KERNEL); + if (!buffer) { + err("unable to allocate memory for configuration descriptors"); + return -ENOMEM; + } + desc = (struct usb_config_descriptor *)buffer; + + for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) { + /* We grab the first 8 bytes so we know how long the whole */ + /* configuration is */ + result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8); + if (result < 8) { + if (result < 0) + err("unable to get descriptor"); + else { + err("config descriptor too short (expected %i, got %i)", 8, result); + result = -EINVAL; + } + goto err; + } + + /* Get the full buffer */ + length = le16_to_cpu(desc->wTotalLength); + + bigbuffer = kmalloc(length, GFP_KERNEL); + if (!bigbuffer) { + err("unable to allocate memory for configuration descriptors"); + result = -ENOMEM; + goto err; + } + + /* Now that we know the length, get the whole thing */ + result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); + if (result < 0) { + err("couldn't get all of config descriptors"); + kfree(bigbuffer); + goto err; + } + + if (result < length) { + err("config descriptor too short (expected %i, got %i)", length, result); + result = -EINVAL; + kfree(bigbuffer); + goto err; + } + + dev->rawdescriptors[cfgno] = bigbuffer; + + result = usb_parse_configuration(&dev->config[cfgno], bigbuffer); + if (result > 0) + dbg("descriptor data left"); + else if (result < 0) { + result = -EINVAL; + goto err; + } + } + + kfree(buffer); + return 0; +err: + kfree(buffer); + dev->descriptor.bNumConfigurations = cfgno; + return result; +} + diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/core/message.c Sun Jun 2 18:44:58 2002 @@ -0,0 +1,661 @@ +/* + * message.c - synchronous message handling + */ + +#include +#include +#include +#include +#include + +struct usb_api_data { + wait_queue_head_t wqh; + int done; +}; + +static void usb_api_blocking_completion(struct urb *urb) +{ + struct usb_api_data *awd = (struct usb_api_data *)urb->context; + + awd->done = 1; + wmb(); + wake_up(&awd->wqh); +} + +// Starts urb and waits for completion or timeout +static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) +{ + DECLARE_WAITQUEUE(wait, current); + struct usb_api_data awd; + int status; + + init_waitqueue_head(&awd.wqh); + awd.done = 0; + + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&awd.wqh, &wait); + + urb->context = &awd; + status = usb_submit_urb(urb, GFP_KERNEL); + if (status) { + // something went wrong + usb_free_urb(urb); + set_current_state(TASK_RUNNING); + remove_wait_queue(&awd.wqh, &wait); + return status; + } + + while (timeout && !awd.done) + { + timeout = schedule_timeout(timeout); + set_current_state(TASK_UNINTERRUPTIBLE); + rmb(); + } + + set_current_state(TASK_RUNNING); + remove_wait_queue(&awd.wqh, &wait); + + if (!timeout && !awd.done) { + if (urb->status != -EINPROGRESS) { /* No callback?!! */ + printk(KERN_ERR "usb: raced timeout, " + "pipe 0x%x status %d time left %d\n", + urb->pipe, urb->status, timeout); + status = urb->status; + } else { + printk("usb_control/bulk_msg: timeout\n"); + usb_unlink_urb(urb); // remove urb safely + status = -ETIMEDOUT; + } + } else + status = urb->status; + + if (actual_length) + *actual_length = urb->actual_length; + + usb_free_urb(urb); + return status; +} + +/*-------------------------------------------------------------------*/ +// returns status (negative) or length (positive) +int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, + struct usb_ctrlrequest *cmd, void *data, int len, int timeout) +{ + struct urb *urb; + int retv; + int length; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + return -ENOMEM; + + FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len, + usb_api_blocking_completion, 0); + + retv = usb_start_wait_urb(urb, timeout, &length); + if (retv < 0) + return retv; + else + return length; +} + +/** + * usb_control_msg - Builds a control urb, sends it off and waits for completion + * @dev: pointer to the usb device to send the message to + * @pipe: endpoint "pipe" to send the message to + * @request: USB message request value + * @requesttype: USB message request type value + * @value: USB message value + * @index: USB message index value + * @data: pointer to the data to send + * @size: length in bytes of the data to send + * @timeout: time in jiffies to wait for the message to complete before + * timing out (if 0 the wait is forever) + * Context: !in_interrupt () + * + * This function sends a simple control message to a specified endpoint + * and waits for the message to complete, or timeout. + * + * If successful, it returns the number of bytes transferred, otherwise a negative error number. + * + * Don't use this function from within an interrupt context, like a + * bottom half handler. If you need an asynchronous message, or need to send + * a message from within interrupt context, use usb_submit_urb() + */ +int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, + __u16 value, __u16 index, void *data, __u16 size, int timeout) +{ + struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); + int ret; + + if (!dr) + return -ENOMEM; + + dr->bRequestType= requesttype; + dr->bRequest = request; + dr->wValue = cpu_to_le16p(&value); + dr->wIndex = cpu_to_le16p(&index); + dr->wLength = cpu_to_le16p(&size); + + //dbg("usb_control_msg"); + + ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout); + + kfree(dr); + + return ret; +} + + +/** + * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion + * @usb_dev: pointer to the usb device to send the message to + * @pipe: endpoint "pipe" to send the message to + * @data: pointer to the data to send + * @len: length in bytes of the data to send + * @actual_length: pointer to a location to put the actual length transferred in bytes + * @timeout: time in jiffies to wait for the message to complete before + * timing out (if 0 the wait is forever) + * Context: !in_interrupt () + * + * This function sends a simple bulk message to a specified endpoint + * and waits for the message to complete, or timeout. + * + * If successful, it returns 0, otherwise a negative error number. + * The number of actual bytes transferred will be stored in the + * actual_length paramater. + * + * Don't use this function from within an interrupt context, like a + * bottom half handler. If you need an asynchronous message, or need to + * send a message from within interrupt context, use usb_submit_urb() + */ +int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, + void *data, int len, int *actual_length, int timeout) +{ + struct urb *urb; + + if (len < 0) + return -EINVAL; + + urb=usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + return -ENOMEM; + + FILL_BULK_URB(urb, usb_dev, pipe, data, len, + usb_api_blocking_completion, 0); + + return usb_start_wait_urb(urb,timeout,actual_length); +} + +/** + * usb_get_descriptor - issues a generic GET_DESCRIPTOR request + * @dev: the device whose descriptor is being retrieved + * @type: the descriptor type (USB_DT_*) + * @index: the number of the descriptor + * @buf: where to put the descriptor + * @size: how big is "buf"? + * Context: !in_interrupt () + * + * Gets a USB descriptor. Convenience functions exist to simplify + * getting some types of descriptors. Use + * usb_get_device_descriptor() for USB_DT_DEVICE, + * and usb_get_string() or usb_string() for USB_DT_STRING. + * Configuration descriptors (USB_DT_CONFIG) are part of the device + * structure, at least for the current configuration. + * In addition to a number of USB-standard descriptors, some + * devices also use class-specific or vendor-specific descriptors. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns the number of bytes received on success, or else the status code + * returned by the underlying usb_control_msg() call. + */ +int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) +{ + int i = 5; + int result; + + memset(buf,0,size); // Make sure we parse really received data + + while (i--) { + /* retries if the returned length was 0; flakey device */ + if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (type << 8) + index, 0, buf, size, + HZ * USB_CTRL_GET_TIMEOUT)) > 0 + || result == -EPIPE) + break; + } + return result; +} + +/** + * usb_get_string - gets a string descriptor + * @dev: the device whose string descriptor is being retrieved + * @langid: code for language chosen (from string descriptor zero) + * @index: the number of the descriptor + * @buf: where to put the string + * @size: how big is "buf"? + * Context: !in_interrupt () + * + * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character, + * in little-endian byte order). + * The usb_string() function will often be a convenient way to turn + * these strings into kernel-printable form. + * + * Strings may be referenced in device, configuration, interface, or other + * descriptors, and could also be used in vendor-specific ways. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns the number of bytes received on success, or else the status code + * returned by the underlying usb_control_msg() call. + */ +int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size) +{ + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (USB_DT_STRING << 8) + index, langid, buf, size, + HZ * USB_CTRL_GET_TIMEOUT); +} + +/** + * usb_get_device_descriptor - (re)reads the device descriptor + * @dev: the device whose device descriptor is being updated + * Context: !in_interrupt () + * + * Updates the copy of the device descriptor stored in the device structure, + * which dedicates space for this purpose. Note that several fields are + * converted to the host CPU's byte order: the USB version (bcdUSB), and + * vendors product and version fields (idVendor, idProduct, and bcdDevice). + * That lets device drivers compare against non-byteswapped constants. + * + * There's normally no need to use this call, although some devices + * will change their descriptors after events like updating firmware. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns the number of bytes received on success, or else the status code + * returned by the underlying usb_control_msg() call. + */ +int usb_get_device_descriptor(struct usb_device *dev) +{ + int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, + sizeof(dev->descriptor)); + if (ret >= 0) { + le16_to_cpus(&dev->descriptor.bcdUSB); + le16_to_cpus(&dev->descriptor.idVendor); + le16_to_cpus(&dev->descriptor.idProduct); + le16_to_cpus(&dev->descriptor.bcdDevice); + } + return ret; +} + +/** + * usb_get_status - issues a GET_STATUS call + * @dev: the device whose status is being checked + * @type: USB_RECIP_*; for device, interface, or endpoint + * @target: zero (for device), else interface or endpoint number + * @data: pointer to two bytes of bitmap data + * Context: !in_interrupt () + * + * Returns device, interface, or endpoint status. Normally only of + * interest to see if the device is self powered, or has enabled the + * remote wakeup facility; or whether a bulk or interrupt endpoint + * is halted ("stalled"). + * + * Bits in these status bitmaps are set using the SET_FEATURE request, + * and cleared using the CLEAR_FEATURE request. The usb_clear_halt() + * function should be used to clear halt ("stall") status. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns the number of bytes received on success, or else the status code + * returned by the underlying usb_control_msg() call. + */ +int usb_get_status(struct usb_device *dev, int type, int target, void *data) +{ + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2, + HZ * USB_CTRL_GET_TIMEOUT); +} + + +// hub-only!! ... and only exported for reset/reinit path. +// otherwise used internally, for config/altsetting reconfig. +void usb_set_maxpacket(struct usb_device *dev) +{ + int i, b; + + for (i=0; iactconfig->bNumInterfaces; i++) { + struct usb_interface *ifp = dev->actconfig->interface + i; + struct usb_interface_descriptor *as = ifp->altsetting + ifp->act_altsetting; + struct usb_endpoint_descriptor *ep = as->endpoint; + int e; + + for (e=0; ebNumEndpoints; e++) { + b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */ + dev->epmaxpacketout[b] = ep[e].wMaxPacketSize; + dev->epmaxpacketin [b] = ep[e].wMaxPacketSize; + } + else if (usb_endpoint_out(ep[e].bEndpointAddress)) { + if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b]) + dev->epmaxpacketout[b] = ep[e].wMaxPacketSize; + } + else { + if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b]) + dev->epmaxpacketin [b] = ep[e].wMaxPacketSize; + } + } + } +} + +/** + * usb_clear_halt - tells device to clear endpoint halt/stall condition + * @dev: device whose endpoint is halted + * @pipe: endpoint "pipe" being cleared + * Context: !in_interrupt () + * + * This is used to clear halt conditions for bulk and interrupt endpoints, + * as reported by URB completion status. Endpoints that are halted are + * sometimes referred to as being "stalled". Such endpoints are unable + * to transmit or receive data until the halt status is cleared. Any URBs + * queued queued for such an endpoint should normally be unlinked before + * clearing the halt condition. + * + * Note that control and isochronous endpoints don't halt, although control + * endpoints report "protocol stall" (for unsupported requests) using the + * same status code used to report a true stall. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns zero on success, or else the status code returned by the + * underlying usb_control_msg() call. + */ +int usb_clear_halt(struct usb_device *dev, int pipe) +{ + int result; + __u16 status; + unsigned char *buffer; + int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7); + +/* + if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp))) + return 0; +*/ + + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, + HZ * USB_CTRL_SET_TIMEOUT); + + /* don't clear if failed */ + if (result < 0) + return result; + + buffer = kmalloc(sizeof(status), GFP_KERNEL); + if (!buffer) { + err("unable to allocate memory for configuration descriptors"); + return -ENOMEM; + } + + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp, + // FIXME USB_CTRL_GET_TIMEOUT, yes? why not usb_get_status() ? + buffer, sizeof(status), HZ * USB_CTRL_SET_TIMEOUT); + + memcpy(&status, buffer, sizeof(status)); + kfree(buffer); + + if (result < 0) + return result; + + if (le16_to_cpu(status) & 1) + return -EPIPE; /* still halted */ + + usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); + + /* toggle is reset on clear */ + + usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); + + return 0; +} + +/** + * usb_set_interface - Makes a particular alternate setting be current + * @dev: the device whose interface is being updated + * @interface: the interface being updated + * @alternate: the setting being chosen. + * Context: !in_interrupt () + * + * This is used to enable data transfers on interfaces that may not + * be enabled by default. Not all devices support such configurability. + * + * Within any given configuration, each interface may have several + * alternative settings. These are often used to control levels of + * bandwidth consumption. For example, the default setting for a high + * speed interrupt endpoint may not send more than about 4KBytes per + * microframe, and isochronous endpoints may never be part of a an + * interface's default setting. To access such bandwidth, alternate + * interface setting must be made current. + * + * Note that in the Linux USB subsystem, bandwidth associated with + * an endpoint in a given alternate setting is not reserved until an + * is submitted that needs that bandwidth. Some other operating systems + * allocate bandwidth early, when a configuration is chosen. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns zero on success, or else the status code returned by the + * underlying usb_control_msg() call. + */ +int usb_set_interface(struct usb_device *dev, int interface, int alternate) +{ + struct usb_interface *iface; + struct usb_interface_descriptor *iface_as; + int i, ret; + + iface = usb_ifnum_to_if(dev, interface); + if (!iface) { + warn("selecting invalid interface %d", interface); + return -EINVAL; + } + + /* 9.4.10 says devices don't need this, if the interface + only has one alternate setting */ + if (iface->num_altsetting == 1) { + dbg("ignoring set_interface for dev %d, iface %d, alt %d", + dev->devnum, interface, alternate); + return 0; + } + + if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate, + interface, NULL, 0, HZ * 5)) < 0) + return ret; + + iface->act_altsetting = alternate; + + /* 9.1.1.5: reset toggles for all endpoints affected by this iface-as + * + * Note: + * Despite EP0 is always present in all interfaces/AS, the list of + * endpoints from the descriptor does not contain EP0. Due to its + * omnipresence one might expect EP0 being considered "affected" by + * any SetInterface request and hence assume toggles need to be reset. + * However, EP0 toggles are re-synced for every individual transfer + * during the SETUP stage - hence EP0 toggles are "don't care" here. + */ + + iface_as = &iface->altsetting[alternate]; + for (i = 0; i < iface_as->bNumEndpoints; i++) { + u8 ep = iface_as->endpoint[i].bEndpointAddress; + + usb_settoggle(dev, ep&USB_ENDPOINT_NUMBER_MASK, usb_endpoint_out(ep), 0); + } + + /* usb_set_maxpacket() sets the maxpacket size for all EP in all + * interfaces but it shouldn't do any harm here: we have changed + * the AS for the requested interface only, hence for unaffected + * interfaces it's just re-application of still-valid values. + */ + usb_set_maxpacket(dev); + return 0; +} + +/** + * usb_set_configuration - Makes a particular device setting be current + * @dev: the device whose configuration is being updated + * @configuration: the configuration being chosen. + * Context: !in_interrupt () + * + * This is used to enable non-default device modes. Not all devices + * support this kind of configurability. By default, configuration + * zero is selected after enumeration; many devices only have a single + * configuration. + * + * USB devices may support one or more configurations, which affect + * power consumption and the functionality available. For example, + * the default configuration is limited to using 100mA of bus power, + * so that when certain device functionality requires more power, + * and the device is bus powered, that functionality will be in some + * non-default device configuration. Other device modes may also be + * reflected as configuration options, such as whether two ISDN + * channels are presented as independent 64Kb/s interfaces or as one + * bonded 128Kb/s interface. + * + * Note that USB has an additional level of device configurability, + * associated with interfaces. That configurability is accessed using + * usb_set_interface(). + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns zero on success, or else the status code returned by the + * underlying usb_control_msg() call. + */ +int usb_set_configuration(struct usb_device *dev, int configuration) +{ + int i, ret; + struct usb_config_descriptor *cp = NULL; + + for (i=0; idescriptor.bNumConfigurations; i++) { + if (dev->config[i].bConfigurationValue == configuration) { + cp = &dev->config[i]; + break; + } + } + if (!cp) { + warn("selecting invalid configuration %d", configuration); + return -EINVAL; + } + + if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_CONFIGURATION, 0, configuration, 0, + NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0) + return ret; + + dev->actconfig = cp; + dev->toggle[0] = 0; + dev->toggle[1] = 0; + usb_set_maxpacket(dev); + + return 0; +} + + +/** + * usb_string - returns ISO 8859-1 version of a string descriptor + * @dev: the device whose string descriptor is being retrieved + * @index: the number of the descriptor + * @buf: where to put the string + * @size: how big is "buf"? + * Context: !in_interrupt () + * + * This converts the UTF-16LE encoded strings returned by devices, from + * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones + * that are more usable in most kernel contexts. Note that all characters + * in the chosen descriptor that can't be encoded using ISO-8859-1 + * are converted to the question mark ("?") character, and this function + * chooses strings in the first language supported by the device. + * + * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit + * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode, + * and is appropriate for use many uses of English and several other + * Western European languages. (But it doesn't include the "Euro" symbol.) + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns length of the string (>= 0) or usb_control_msg status (< 0). + */ +int usb_string(struct usb_device *dev, int index, char *buf, size_t size) +{ + unsigned char *tbuf; + int err; + unsigned int u, idx; + + if (size <= 0 || !buf || !index) + return -EINVAL; + buf[0] = 0; + tbuf = kmalloc(256, GFP_KERNEL); + if (!tbuf) + return -ENOMEM; + + /* get langid for strings if it's not yet known */ + if (!dev->have_langid) { + err = usb_get_string(dev, 0, 0, tbuf, 4); + if (err < 0) { + err("error getting string descriptor 0 (error=%d)", err); + goto errout; + } else if (tbuf[0] < 4) { + err("string descriptor 0 too short"); + err = -EINVAL; + goto errout; + } else { + dev->have_langid = -1; + dev->string_langid = tbuf[2] | (tbuf[3]<< 8); + /* always use the first langid listed */ + dbg("USB device number %d default language ID 0x%x", + dev->devnum, dev->string_langid); + } + } + + /* + * Just ask for a maximum length string and then take the length + * that was returned. + */ + err = usb_get_string(dev, dev->string_langid, index, tbuf, 255); + if (err < 0) + goto errout; + + size--; /* leave room for trailing NULL char in output buffer */ + for (idx = 0, u = 2; u < err; u += 2) { + if (idx >= size) + break; + if (tbuf[u+1]) /* high byte */ + buf[idx++] = '?'; /* non ISO-8859-1 character */ + else + buf[idx++] = tbuf[u]; + } + buf[idx] = 0; + err = idx; + + errout: + kfree(tbuf); + return err; +} + +// synchronous request completion model +EXPORT_SYMBOL(usb_control_msg); +EXPORT_SYMBOL(usb_bulk_msg); +// synchronous control message convenience routines +EXPORT_SYMBOL(usb_get_descriptor); +EXPORT_SYMBOL(usb_get_device_descriptor); +EXPORT_SYMBOL(usb_get_status); +EXPORT_SYMBOL(usb_get_string); +EXPORT_SYMBOL(usb_string); +EXPORT_SYMBOL(usb_clear_halt); +EXPORT_SYMBOL(usb_set_configuration); +EXPORT_SYMBOL(usb_set_interface); + diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/core/urb.c Sun Jun 2 18:44:58 2002 @@ -0,0 +1,236 @@ +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include +#include "hcd.h" + +/** + * usb_alloc_urb - creates a new urb for a USB driver to use + * @iso_packets: number of iso packets for this urb + * @mem_flags: the type of memory to allocate, see kmalloc() for a list of + * valid options for this. + * + * Creates an urb for the USB driver to use, initializes a few internal + * structures, incrementes the usage counter, and returns a pointer to it. + * + * If no memory is available, NULL is returned. + * + * If the driver want to use this urb for interrupt, control, or bulk + * endpoints, pass '0' as the number of iso packets. + * + * The driver must call usb_free_urb() when it is finished with the urb. + */ +struct urb *usb_alloc_urb(int iso_packets, int mem_flags) +{ + struct urb *urb; + + urb = (struct urb *)kmalloc(sizeof(struct urb) + + iso_packets * sizeof(struct usb_iso_packet_descriptor), + mem_flags); + if (!urb) { + err("alloc_urb: kmalloc failed"); + return NULL; + } + + memset(urb, 0, sizeof(*urb)); + urb->count = (atomic_t)ATOMIC_INIT(1); + spin_lock_init(&urb->lock); + + return urb; +} + +/** + * usb_free_urb - frees the memory used by a urb when all users of it are finished + * @urb: pointer to the urb to free + * + * Must be called when a user of a urb is finished with it. When the last user + * of the urb calls this function, the memory of the urb is freed. + * + * Note: The transfer buffer associated with the urb is not freed, that must be + * done elsewhere. + */ +void usb_free_urb(struct urb *urb) +{ + if (urb) + if (atomic_dec_and_test(&urb->count)) + kfree(urb); +} + +/** + * usb_get_urb - increments the reference count of the urb + * @urb: pointer to the urb to modify + * + * This must be called whenever a urb is transfered from a device driver to a + * host controller driver. This allows proper reference counting to happen + * for urbs. + * + * A pointer to the urb with the incremented reference counter is returned. + */ +struct urb * usb_get_urb(struct urb *urb) +{ + if (urb) { + atomic_inc(&urb->count); + return urb; + } else + return NULL; +} + + +/*-------------------------------------------------------------------*/ + +/** + * usb_submit_urb - asynchronously issue a transfer request for an endpoint + * @urb: pointer to the urb describing the request + * @mem_flags: the type of memory to allocate, see kmalloc() for a list + * of valid options for this. + * + * This submits a transfer request, and transfers control of the URB + * describing that request to the USB subsystem. Request completion will + * indicated later, asynchronously, by calling the completion handler. + * This call may be issued in interrupt context. + * + * The caller must have correctly initialized the URB before submitting + * it. Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are + * available to ensure that most fields are correctly initialized, for + * the particular kind of transfer, although they will not initialize + * any transfer flags. + * + * Successful submissions return 0; otherwise this routine returns a + * negative error number. If the submission is successful, the complete + * fuction of the urb will be called when the USB host driver is + * finished with the urb (either a successful transmission, or some + * error case.) + * + * Unreserved Bandwidth Transfers: + * + * Bulk or control requests complete only once. When the completion + * function is called, control of the URB is returned to the device + * driver which issued the request. The completion handler may then + * immediately free or reuse that URB. + * + * Bulk URBs will be queued if the USB_QUEUE_BULK transfer flag is set + * in the URB. This can be used to maximize bandwidth utilization by + * letting the USB controller start work on the next URB without any + * delay to report completion (scheduling and processing an interrupt) + * and then submit that next request. + * + * For control endpoints, the synchronous usb_control_msg() call is + * often used (in non-interrupt context) instead of this call. + * + * Reserved Bandwidth Transfers: + * + * Periodic URBs (interrupt or isochronous) are completed repeatedly, + * until the original request is aborted. When the completion callback + * indicates the URB has been unlinked (with a special status code), + * control of that URB returns to the device driver. Otherwise, the + * completion handler does not control the URB, and should not change + * any of its fields. + * + * Note that isochronous URBs should be submitted in a "ring" data + * structure (using urb->next) to ensure that they are resubmitted + * appropriately. + * + * If the USB subsystem can't reserve sufficient bandwidth to perform + * the periodic request, and bandwidth reservation is being done for + * this controller, submitting such a periodic request will fail. + * + * Memory Flags: + * + * General rules for how to decide which mem_flags to use: + * + * Basically the rules are the same as for kmalloc. There are four + * different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and + * GFP_ATOMIC. + * + * GFP_NOFS is not ever used, as it has not been implemented yet. + * + * There are three situations you must use GFP_ATOMIC. + * a) you are inside a completion handler, an interrupt, bottom half, + * tasklet or timer. + * b) you are holding a spinlock or rwlock (does not apply to + * semaphores) + * c) current->state != TASK_RUNNING, this is the case only after + * you've changed it. + * + * GFP_NOIO is used in the block io path and error handling of storage + * devices. + * + * All other situations use GFP_KERNEL. + * + * Specfic rules for how to decide which mem_flags to use: + * + * - start_xmit, timeout, and receive methods of network drivers must + * use GFP_ATOMIC (spinlock) + * - queuecommand methods of scsi drivers must use GFP_ATOMIC (spinlock) + * - If you use a kernel thread with a network driver you must use + * GFP_NOIO, unless b) or c) apply + * - After you have done a down() you use GFP_KERNEL, unless b) or c) + * apply or your are in a storage driver's block io path + * - probe and disconnect use GFP_KERNEL unless b) or c) apply + * - Changing firmware on a running storage or net device uses + * GFP_NOIO, unless b) or c) apply + * + */ +int usb_submit_urb(struct urb *urb, int mem_flags) +{ + + if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) { + if (usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)) <= 0) { + err("%s: pipe %x has invalid size (<= 0)", __FUNCTION__, urb->pipe); + return -EMSGSIZE; + } + return urb->dev->bus->op->submit_urb(urb, mem_flags); + } + return -ENODEV; +} + +/*-------------------------------------------------------------------*/ + +/** + * usb_unlink_urb - abort/cancel a transfer request for an endpoint + * @urb: pointer to urb describing a previously submitted request + * + * This routine cancels an in-progress request. The requests's + * completion handler will be called with a status code indicating + * that the request has been canceled, and that control of the URB + * has been returned to that device driver. This is the only way + * to stop an interrupt transfer, so long as the device is connected. + * + * When the USB_ASYNC_UNLINK transfer flag for the URB is clear, this + * request is synchronous. Success is indicated by returning zero, + * at which time the urb will have been unlinked, + * and the completion function will see status -ENOENT. Failure is + * indicated by any other return value. This mode may not be used + * when unlinking an urb from an interrupt context, such as a bottom + * half or a completion handler, + * + * When the USB_ASYNC_UNLINK transfer flag for the URB is set, this + * request is asynchronous. Success is indicated by returning -EINPROGRESS, + * at which time the urb will normally not have been unlinked, + * and the completion function will see status -ECONNRESET. Failure is + * indicated by any other return value. + */ +int usb_unlink_urb(struct urb *urb) +{ + if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) + return urb->dev->bus->op->unlink_urb(urb); + else + return -ENODEV; +} + +// asynchronous request completion model +EXPORT_SYMBOL(usb_alloc_urb); +EXPORT_SYMBOL(usb_free_urb); +EXPORT_SYMBOL(usb_get_urb); +EXPORT_SYMBOL(usb_submit_urb); +EXPORT_SYMBOL(usb_unlink_urb); + diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c Sun Jun 2 18:44:57 2002 +++ b/drivers/usb/core/usb.c Sun Jun 2 18:44:57 2002 @@ -33,7 +33,6 @@ #include #include #include -#include #ifdef CONFIG_USB_DEBUG #define DEBUG @@ -904,7 +903,8 @@ /* register this interface with driverfs */ interface->dev.parent = &dev->dev; - sprintf (&interface->dev.bus_id[0], "%03d", ifnum); + interface->dev.bus = &usb_bus_type; + sprintf (&interface->dev.bus_id[0], "%03d%03d", dev->devnum,ifnum); sprintf (&interface->dev.name[0], "figure out some name..."); device_register (&interface->dev); @@ -1013,401 +1013,6 @@ } } -/** - * usb_alloc_urb - creates a new urb for a USB driver to use - * @iso_packets: number of iso packets for this urb - * @mem_flags: the type of memory to allocate, see kmalloc() for a list of - * valid options for this. - * - * Creates an urb for the USB driver to use, initializes a few internal - * structures, incrementes the usage counter, and returns a pointer to it. - * - * If no memory is available, NULL is returned. - * - * If the driver want to use this urb for interrupt, control, or bulk - * endpoints, pass '0' as the number of iso packets. - * - * The driver must call usb_free_urb() when it is finished with the urb. - */ -struct urb *usb_alloc_urb(int iso_packets, int mem_flags) -{ - struct urb *urb; - - urb = (struct urb *)kmalloc(sizeof(struct urb) + - iso_packets * sizeof(struct usb_iso_packet_descriptor), - mem_flags); - if (!urb) { - err("alloc_urb: kmalloc failed"); - return NULL; - } - - memset(urb, 0, sizeof(*urb)); - urb->count = (atomic_t)ATOMIC_INIT(1); - spin_lock_init(&urb->lock); - - return urb; -} - -/** - * usb_free_urb - frees the memory used by a urb when all users of it are finished - * @urb: pointer to the urb to free - * - * Must be called when a user of a urb is finished with it. When the last user - * of the urb calls this function, the memory of the urb is freed. - * - * Note: The transfer buffer associated with the urb is not freed, that must be - * done elsewhere. - */ -void usb_free_urb(struct urb *urb) -{ - if (urb) - if (atomic_dec_and_test(&urb->count)) - kfree(urb); -} - -/** - * usb_get_urb - increments the reference count of the urb - * @urb: pointer to the urb to modify - * - * This must be called whenever a urb is transfered from a device driver to a - * host controller driver. This allows proper reference counting to happen - * for urbs. - * - * A pointer to the urb with the incremented reference counter is returned. - */ -struct urb * usb_get_urb(struct urb *urb) -{ - if (urb) { - atomic_inc(&urb->count); - return urb; - } else - return NULL; -} - - -/*-------------------------------------------------------------------*/ - -/** - * usb_submit_urb - asynchronously issue a transfer request for an endpoint - * @urb: pointer to the urb describing the request - * @mem_flags: the type of memory to allocate, see kmalloc() for a list - * of valid options for this. - * - * This submits a transfer request, and transfers control of the URB - * describing that request to the USB subsystem. Request completion will - * indicated later, asynchronously, by calling the completion handler. - * This call may be issued in interrupt context. - * - * The caller must have correctly initialized the URB before submitting - * it. Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are - * available to ensure that most fields are correctly initialized, for - * the particular kind of transfer, although they will not initialize - * any transfer flags. - * - * Successful submissions return 0; otherwise this routine returns a - * negative error number. If the submission is successful, the complete - * fuction of the urb will be called when the USB host driver is - * finished with the urb (either a successful transmission, or some - * error case.) - * - * Unreserved Bandwidth Transfers: - * - * Bulk or control requests complete only once. When the completion - * function is called, control of the URB is returned to the device - * driver which issued the request. The completion handler may then - * immediately free or reuse that URB. - * - * Bulk URBs will be queued if the USB_QUEUE_BULK transfer flag is set - * in the URB. This can be used to maximize bandwidth utilization by - * letting the USB controller start work on the next URB without any - * delay to report completion (scheduling and processing an interrupt) - * and then submit that next request. - * - * For control endpoints, the synchronous usb_control_msg() call is - * often used (in non-interrupt context) instead of this call. - * - * Reserved Bandwidth Transfers: - * - * Periodic URBs (interrupt or isochronous) are completed repeatedly, - * until the original request is aborted. When the completion callback - * indicates the URB has been unlinked (with a special status code), - * control of that URB returns to the device driver. Otherwise, the - * completion handler does not control the URB, and should not change - * any of its fields. - * - * Note that isochronous URBs should be submitted in a "ring" data - * structure (using urb->next) to ensure that they are resubmitted - * appropriately. - * - * If the USB subsystem can't reserve sufficient bandwidth to perform - * the periodic request, and bandwidth reservation is being done for - * this controller, submitting such a periodic request will fail. - * - * Memory Flags: - * - * General rules for how to decide which mem_flags to use: - * - * Basically the rules are the same as for kmalloc. There are four - * different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and - * GFP_ATOMIC. - * - * GFP_NOFS is not ever used, as it has not been implemented yet. - * - * There are three situations you must use GFP_ATOMIC. - * a) you are inside a completion handler, an interrupt, bottom half, - * tasklet or timer. - * b) you are holding a spinlock or rwlock (does not apply to - * semaphores) - * c) current->state != TASK_RUNNING, this is the case only after - * you've changed it. - * - * GFP_NOIO is used in the block io path and error handling of storage - * devices. - * - * All other situations use GFP_KERNEL. - * - * Specfic rules for how to decide which mem_flags to use: - * - * - start_xmit, timeout, and receive methods of network drivers must - * use GFP_ATOMIC (spinlock) - * - queuecommand methods of scsi drivers must use GFP_ATOMIC (spinlock) - * - If you use a kernel thread with a network driver you must use - * GFP_NOIO, unless b) or c) apply - * - After you have done a down() you use GFP_KERNEL, unless b) or c) - * apply or your are in a storage driver's block io path - * - probe and disconnect use GFP_KERNEL unless b) or c) apply - * - Changing firmware on a running storage or net device uses - * GFP_NOIO, unless b) or c) apply - * - */ -int usb_submit_urb(struct urb *urb, int mem_flags) -{ - - if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) { - if (usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)) <= 0) { - err("%s: pipe %x has invalid size (<= 0)", __FUNCTION__, urb->pipe); - return -EMSGSIZE; - } - return urb->dev->bus->op->submit_urb(urb, mem_flags); - } - return -ENODEV; -} - -/*-------------------------------------------------------------------*/ - -/** - * usb_unlink_urb - abort/cancel a transfer request for an endpoint - * @urb: pointer to urb describing a previously submitted request - * - * This routine cancels an in-progress request. The requests's - * completion handler will be called with a status code indicating - * that the request has been canceled, and that control of the URB - * has been returned to that device driver. This is the only way - * to stop an interrupt transfer, so long as the device is connected. - * - * When the USB_ASYNC_UNLINK transfer flag for the URB is clear, this - * request is synchronous. Success is indicated by returning zero, - * at which time the urb will have been unlinked, - * and the completion function will see status -ENOENT. Failure is - * indicated by any other return value. This mode may not be used - * when unlinking an urb from an interrupt context, such as a bottom - * half or a completion handler, - * - * When the USB_ASYNC_UNLINK transfer flag for the URB is set, this - * request is asynchronous. Success is indicated by returning -EINPROGRESS, - * at which time the urb will normally not have been unlinked, - * and the completion function will see status -ECONNRESET. Failure is - * indicated by any other return value. - */ -int usb_unlink_urb(struct urb *urb) -{ - if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) - return urb->dev->bus->op->unlink_urb(urb); - else - return -ENODEV; -} -/*-------------------------------------------------------------------* - * SYNCHRONOUS CALLS * - *-------------------------------------------------------------------*/ - -struct usb_api_data { - wait_queue_head_t wqh; - int done; -}; - -static void usb_api_blocking_completion(struct urb *urb) -{ - struct usb_api_data *awd = (struct usb_api_data *)urb->context; - - awd->done = 1; - wmb(); - wake_up(&awd->wqh); -} - -// Starts urb and waits for completion or timeout -static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) -{ - DECLARE_WAITQUEUE(wait, current); - struct usb_api_data awd; - int status; - - init_waitqueue_head(&awd.wqh); - awd.done = 0; - - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&awd.wqh, &wait); - - urb->context = &awd; - status = usb_submit_urb(urb, GFP_KERNEL); - if (status) { - // something went wrong - usb_free_urb(urb); - set_current_state(TASK_RUNNING); - remove_wait_queue(&awd.wqh, &wait); - return status; - } - - while (timeout && !awd.done) - { - timeout = schedule_timeout(timeout); - set_current_state(TASK_UNINTERRUPTIBLE); - rmb(); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&awd.wqh, &wait); - - if (!timeout && !awd.done) { - if (urb->status != -EINPROGRESS) { /* No callback?!! */ - printk(KERN_ERR "usb: raced timeout, " - "pipe 0x%x status %d time left %d\n", - urb->pipe, urb->status, timeout); - status = urb->status; - } else { - printk("usb_control/bulk_msg: timeout\n"); - usb_unlink_urb(urb); // remove urb safely - status = -ETIMEDOUT; - } - } else - status = urb->status; - - if (actual_length) - *actual_length = urb->actual_length; - - usb_free_urb(urb); - return status; -} - -/*-------------------------------------------------------------------*/ -// returns status (negative) or length (positive) -int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, - struct usb_ctrlrequest *cmd, void *data, int len, int timeout) -{ - struct urb *urb; - int retv; - int length; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - return -ENOMEM; - - FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len, - usb_api_blocking_completion, 0); - - retv = usb_start_wait_urb(urb, timeout, &length); - if (retv < 0) - return retv; - else - return length; -} - -/** - * usb_control_msg - Builds a control urb, sends it off and waits for completion - * @dev: pointer to the usb device to send the message to - * @pipe: endpoint "pipe" to send the message to - * @request: USB message request value - * @requesttype: USB message request type value - * @value: USB message value - * @index: USB message index value - * @data: pointer to the data to send - * @size: length in bytes of the data to send - * @timeout: time in jiffies to wait for the message to complete before - * timing out (if 0 the wait is forever) - * Context: !in_interrupt () - * - * This function sends a simple control message to a specified endpoint - * and waits for the message to complete, or timeout. - * - * If successful, it returns the number of bytes transferred, otherwise a negative error number. - * - * Don't use this function from within an interrupt context, like a - * bottom half handler. If you need an asynchronous message, or need to send - * a message from within interrupt context, use usb_submit_urb() - */ -int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, - __u16 value, __u16 index, void *data, __u16 size, int timeout) -{ - struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); - int ret; - - if (!dr) - return -ENOMEM; - - dr->bRequestType= requesttype; - dr->bRequest = request; - dr->wValue = cpu_to_le16p(&value); - dr->wIndex = cpu_to_le16p(&index); - dr->wLength = cpu_to_le16p(&size); - - //dbg("usb_control_msg"); - - ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout); - - kfree(dr); - - return ret; -} - - -/** - * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion - * @usb_dev: pointer to the usb device to send the message to - * @pipe: endpoint "pipe" to send the message to - * @data: pointer to the data to send - * @len: length in bytes of the data to send - * @actual_length: pointer to a location to put the actual length transferred in bytes - * @timeout: time in jiffies to wait for the message to complete before - * timing out (if 0 the wait is forever) - * Context: !in_interrupt () - * - * This function sends a simple bulk message to a specified endpoint - * and waits for the message to complete, or timeout. - * - * If successful, it returns 0, otherwise a negative error number. - * The number of actual bytes transferred will be stored in the - * actual_length paramater. - * - * Don't use this function from within an interrupt context, like a - * bottom half handler. If you need an asynchronous message, or need to - * send a message from within interrupt context, use usb_submit_urb() - */ -int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, - void *data, int len, int *actual_length, int timeout) -{ - struct urb *urb; - - if (len < 0) - return -EINVAL; - - urb=usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - return -ENOMEM; - - FILL_BULK_URB(urb, usb_dev, pipe, data, len, - usb_api_blocking_completion, 0); - - return usb_start_wait_urb(urb,timeout,actual_length); -} /** * usb_get_current_frame_number - return current bus frame number @@ -1429,390 +1034,6 @@ /*-------------------------------------------------------------------*/ -static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size) -{ - struct usb_descriptor_header *header; - unsigned char *begin; - int parsed = 0, len, numskipped; - - header = (struct usb_descriptor_header *)buffer; - - /* Everything should be fine being passed into here, but we sanity */ - /* check JIC */ - if (header->bLength > size) { - err("ran out of descriptors parsing"); - return -1; - } - - if (header->bDescriptorType != USB_DT_ENDPOINT) { - warn("unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X", - endpoint->bDescriptorType, USB_DT_ENDPOINT); - return parsed; - } - - if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) - memcpy(endpoint, buffer, USB_DT_ENDPOINT_AUDIO_SIZE); - else - memcpy(endpoint, buffer, USB_DT_ENDPOINT_SIZE); - - le16_to_cpus(&endpoint->wMaxPacketSize); - - buffer += header->bLength; - size -= header->bLength; - parsed += header->bLength; - - /* Skip over the rest of the Class Specific or Vendor Specific */ - /* descriptors */ - begin = buffer; - numskipped = 0; - while (size >= sizeof(struct usb_descriptor_header)) { - header = (struct usb_descriptor_header *)buffer; - - if (header->bLength < 2) { - err("invalid descriptor length of %d", header->bLength); - return -1; - } - - /* If we find another "proper" descriptor then we're done */ - if ((header->bDescriptorType == USB_DT_ENDPOINT) || - (header->bDescriptorType == USB_DT_INTERFACE) || - (header->bDescriptorType == USB_DT_CONFIG) || - (header->bDescriptorType == USB_DT_DEVICE)) - break; - - dbg("skipping descriptor 0x%X", - header->bDescriptorType); - numskipped++; - - buffer += header->bLength; - size -= header->bLength; - parsed += header->bLength; - } - if (numskipped) - dbg("skipped %d class/vendor specific endpoint descriptors", numskipped); - - /* Copy any unknown descriptors into a storage area for drivers */ - /* to later parse */ - len = (int)(buffer - begin); - if (!len) { - endpoint->extra = NULL; - endpoint->extralen = 0; - return parsed; - } - - endpoint->extra = kmalloc(len, GFP_KERNEL); - - if (!endpoint->extra) { - err("couldn't allocate memory for endpoint extra descriptors"); - endpoint->extralen = 0; - return parsed; - } - - memcpy(endpoint->extra, begin, len); - endpoint->extralen = len; - - return parsed; -} - -static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size) -{ - int i, len, numskipped, retval, parsed = 0; - struct usb_descriptor_header *header; - struct usb_interface_descriptor *ifp; - unsigned char *begin; - - interface->act_altsetting = 0; - interface->num_altsetting = 0; - interface->max_altsetting = USB_ALTSETTINGALLOC; - - interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL); - - if (!interface->altsetting) { - err("couldn't kmalloc interface->altsetting"); - return -1; - } - - while (size > 0) { - if (interface->num_altsetting >= interface->max_altsetting) { - void *ptr; - int oldmas; - - oldmas = interface->max_altsetting; - interface->max_altsetting += USB_ALTSETTINGALLOC; - if (interface->max_altsetting > USB_MAXALTSETTING) { - warn("too many alternate settings (max %d)", - USB_MAXALTSETTING); - return -1; - } - - ptr = interface->altsetting; - interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL); - if (!interface->altsetting) { - err("couldn't kmalloc interface->altsetting"); - interface->altsetting = ptr; - return -1; - } - memcpy(interface->altsetting, ptr, sizeof(struct usb_interface_descriptor) * oldmas); - - kfree(ptr); - } - - ifp = interface->altsetting + interface->num_altsetting; - ifp->endpoint = NULL; - ifp->extra = NULL; - ifp->extralen = 0; - interface->num_altsetting++; - - memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE); - - /* Skip over the interface */ - buffer += ifp->bLength; - parsed += ifp->bLength; - size -= ifp->bLength; - - begin = buffer; - numskipped = 0; - - /* Skip over any interface, class or vendor descriptors */ - while (size >= sizeof(struct usb_descriptor_header)) { - header = (struct usb_descriptor_header *)buffer; - - if (header->bLength < 2) { - err("invalid descriptor length of %d", header->bLength); - return -1; - } - - /* If we find another "proper" descriptor then we're done */ - if ((header->bDescriptorType == USB_DT_INTERFACE) || - (header->bDescriptorType == USB_DT_ENDPOINT) || - (header->bDescriptorType == USB_DT_CONFIG) || - (header->bDescriptorType == USB_DT_DEVICE)) - break; - - numskipped++; - - buffer += header->bLength; - parsed += header->bLength; - size -= header->bLength; - } - - if (numskipped) - dbg("skipped %d class/vendor specific interface descriptors", numskipped); - - /* Copy any unknown descriptors into a storage area for */ - /* drivers to later parse */ - len = (int)(buffer - begin); - if (len) { - ifp->extra = kmalloc(len, GFP_KERNEL); - - if (!ifp->extra) { - err("couldn't allocate memory for interface extra descriptors"); - ifp->extralen = 0; - return -1; - } - memcpy(ifp->extra, begin, len); - ifp->extralen = len; - } - - /* Did we hit an unexpected descriptor? */ - header = (struct usb_descriptor_header *)buffer; - if ((size >= sizeof(struct usb_descriptor_header)) && - ((header->bDescriptorType == USB_DT_CONFIG) || - (header->bDescriptorType == USB_DT_DEVICE))) - return parsed; - - if (ifp->bNumEndpoints > USB_MAXENDPOINTS) { - warn("too many endpoints"); - return -1; - } - - ifp->endpoint = (struct usb_endpoint_descriptor *) - kmalloc(ifp->bNumEndpoints * - sizeof(struct usb_endpoint_descriptor), GFP_KERNEL); - if (!ifp->endpoint) { - err("out of memory"); - return -1; - } - - memset(ifp->endpoint, 0, ifp->bNumEndpoints * - sizeof(struct usb_endpoint_descriptor)); - - for (i = 0; i < ifp->bNumEndpoints; i++) { - header = (struct usb_descriptor_header *)buffer; - - if (header->bLength > size) { - err("ran out of descriptors parsing"); - return -1; - } - - retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size); - if (retval < 0) - return retval; - - buffer += retval; - parsed += retval; - size -= retval; - } - - /* We check to see if it's an alternate to this one */ - ifp = (struct usb_interface_descriptor *)buffer; - if (size < USB_DT_INTERFACE_SIZE || - ifp->bDescriptorType != USB_DT_INTERFACE || - !ifp->bAlternateSetting) - return parsed; - } - - return parsed; -} - -int usb_parse_configuration(struct usb_config_descriptor *config, char *buffer) -{ - int i, retval, size; - struct usb_descriptor_header *header; - - memcpy(config, buffer, USB_DT_CONFIG_SIZE); - le16_to_cpus(&config->wTotalLength); - size = config->wTotalLength; - - if (config->bNumInterfaces > USB_MAXINTERFACES) { - warn("too many interfaces"); - return -1; - } - - config->interface = (struct usb_interface *) - kmalloc(config->bNumInterfaces * - sizeof(struct usb_interface), GFP_KERNEL); - dbg("kmalloc IF %p, numif %i", config->interface, config->bNumInterfaces); - if (!config->interface) { - err("out of memory"); - return -1; - } - - memset(config->interface, 0, - config->bNumInterfaces * sizeof(struct usb_interface)); - - buffer += config->bLength; - size -= config->bLength; - - config->extra = NULL; - config->extralen = 0; - - for (i = 0; i < config->bNumInterfaces; i++) { - int numskipped, len; - char *begin; - - /* Skip over the rest of the Class Specific or Vendor */ - /* Specific descriptors */ - begin = buffer; - numskipped = 0; - while (size >= sizeof(struct usb_descriptor_header)) { - header = (struct usb_descriptor_header *)buffer; - - if ((header->bLength > size) || (header->bLength < 2)) { - err("invalid descriptor length of %d", header->bLength); - return -1; - } - - /* If we find another "proper" descriptor then we're done */ - if ((header->bDescriptorType == USB_DT_ENDPOINT) || - (header->bDescriptorType == USB_DT_INTERFACE) || - (header->bDescriptorType == USB_DT_CONFIG) || - (header->bDescriptorType == USB_DT_DEVICE)) - break; - - dbg("skipping descriptor 0x%X", header->bDescriptorType); - numskipped++; - - buffer += header->bLength; - size -= header->bLength; - } - if (numskipped) - dbg("skipped %d class/vendor specific endpoint descriptors", numskipped); - - /* Copy any unknown descriptors into a storage area for */ - /* drivers to later parse */ - len = (int)(buffer - begin); - if (len) { - if (config->extralen) { - warn("extra config descriptor"); - } else { - config->extra = kmalloc(len, GFP_KERNEL); - if (!config->extra) { - err("couldn't allocate memory for config extra descriptors"); - config->extralen = 0; - return -1; - } - - memcpy(config->extra, begin, len); - config->extralen = len; - } - } - - retval = usb_parse_interface(config->interface + i, buffer, size); - if (retval < 0) - return retval; - - buffer += retval; - size -= retval; - } - - return size; -} - -// hub-only!! ... and only exported for reset/reinit path. -// otherwise used internally on disconnect/destroy path -void usb_destroy_configuration(struct usb_device *dev) -{ - int c, i, j, k; - - if (!dev->config) - return; - - if (dev->rawdescriptors) { - for (i = 0; i < dev->descriptor.bNumConfigurations; i++) - kfree(dev->rawdescriptors[i]); - - kfree(dev->rawdescriptors); - } - - for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { - struct usb_config_descriptor *cf = &dev->config[c]; - - if (!cf->interface) - break; - - for (i = 0; i < cf->bNumInterfaces; i++) { - struct usb_interface *ifp = - &cf->interface[i]; - - if (!ifp->altsetting) - break; - - for (j = 0; j < ifp->num_altsetting; j++) { - struct usb_interface_descriptor *as = - &ifp->altsetting[j]; - - if(as->extra) { - kfree(as->extra); - } - - if (!as->endpoint) - break; - - for(k = 0; k < as->bNumEndpoints; k++) { - if(as->endpoint[k].extra) { - kfree(as->endpoint[k].extra); - } - } - kfree(as->endpoint); - } - - kfree(ifp->altsetting); - } - kfree(cf->interface); - } - kfree(dev->config); -} /* for returning string descriptors in UTF-16LE */ static int ascii2utf (char *ascii, __u8 *utf, int utfmax) @@ -2012,565 +1233,6 @@ 0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT); } -/** - * usb_get_descriptor - issues a generic GET_DESCRIPTOR request - * @dev: the device whose descriptor is being retrieved - * @type: the descriptor type (USB_DT_*) - * @index: the number of the descriptor - * @buf: where to put the descriptor - * @size: how big is "buf"? - * Context: !in_interrupt () - * - * Gets a USB descriptor. Convenience functions exist to simplify - * getting some types of descriptors. Use - * usb_get_device_descriptor() for USB_DT_DEVICE, - * and usb_get_string() or usb_string() for USB_DT_STRING. - * Configuration descriptors (USB_DT_CONFIG) are part of the device - * structure, at least for the current configuration. - * In addition to a number of USB-standard descriptors, some - * devices also use class-specific or vendor-specific descriptors. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns the number of bytes received on success, or else the status code - * returned by the underlying usb_control_msg() call. - */ -int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) -{ - int i = 5; - int result; - - memset(buf,0,size); // Make sure we parse really received data - - while (i--) { - /* retries if the returned length was 0; flakey device */ - if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, - (type << 8) + index, 0, buf, size, - HZ * USB_CTRL_GET_TIMEOUT)) > 0 - || result == -EPIPE) - break; - } - return result; -} - -/** - * usb_get_string - gets a string descriptor - * @dev: the device whose string descriptor is being retrieved - * @langid: code for language chosen (from string descriptor zero) - * @index: the number of the descriptor - * @buf: where to put the string - * @size: how big is "buf"? - * Context: !in_interrupt () - * - * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character, - * in little-endian byte order). - * The usb_string() function will often be a convenient way to turn - * these strings into kernel-printable form. - * - * Strings may be referenced in device, configuration, interface, or other - * descriptors, and could also be used in vendor-specific ways. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns the number of bytes received on success, or else the status code - * returned by the underlying usb_control_msg() call. - */ -int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, - (USB_DT_STRING << 8) + index, langid, buf, size, - HZ * USB_CTRL_GET_TIMEOUT); -} - -/** - * usb_get_device_descriptor - (re)reads the device descriptor - * @dev: the device whose device descriptor is being updated - * Context: !in_interrupt () - * - * Updates the copy of the device descriptor stored in the device structure, - * which dedicates space for this purpose. Note that several fields are - * converted to the host CPU's byte order: the USB version (bcdUSB), and - * vendors product and version fields (idVendor, idProduct, and bcdDevice). - * That lets device drivers compare against non-byteswapped constants. - * - * There's normally no need to use this call, although some devices - * will change their descriptors after events like updating firmware. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns the number of bytes received on success, or else the status code - * returned by the underlying usb_control_msg() call. - */ -int usb_get_device_descriptor(struct usb_device *dev) -{ - int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, - sizeof(dev->descriptor)); - if (ret >= 0) { - le16_to_cpus(&dev->descriptor.bcdUSB); - le16_to_cpus(&dev->descriptor.idVendor); - le16_to_cpus(&dev->descriptor.idProduct); - le16_to_cpus(&dev->descriptor.bcdDevice); - } - return ret; -} - -/** - * usb_get_status - issues a GET_STATUS call - * @dev: the device whose status is being checked - * @type: USB_RECIP_*; for device, interface, or endpoint - * @target: zero (for device), else interface or endpoint number - * @data: pointer to two bytes of bitmap data - * Context: !in_interrupt () - * - * Returns device, interface, or endpoint status. Normally only of - * interest to see if the device is self powered, or has enabled the - * remote wakeup facility; or whether a bulk or interrupt endpoint - * is halted ("stalled"). - * - * Bits in these status bitmaps are set using the SET_FEATURE request, - * and cleared using the CLEAR_FEATURE request. The usb_clear_halt() - * function should be used to clear halt ("stall") status. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns the number of bytes received on success, or else the status code - * returned by the underlying usb_control_msg() call. - */ -int usb_get_status(struct usb_device *dev, int type, int target, void *data) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2, - HZ * USB_CTRL_GET_TIMEOUT); -} - - -// hub-only!! ... and only exported for reset/reinit path. -// otherwise used internally, for config/altsetting reconfig. -void usb_set_maxpacket(struct usb_device *dev) -{ - int i, b; - - for (i=0; iactconfig->bNumInterfaces; i++) { - struct usb_interface *ifp = dev->actconfig->interface + i; - struct usb_interface_descriptor *as = ifp->altsetting + ifp->act_altsetting; - struct usb_endpoint_descriptor *ep = as->endpoint; - int e; - - for (e=0; ebNumEndpoints; e++) { - b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */ - dev->epmaxpacketout[b] = ep[e].wMaxPacketSize; - dev->epmaxpacketin [b] = ep[e].wMaxPacketSize; - } - else if (usb_endpoint_out(ep[e].bEndpointAddress)) { - if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b]) - dev->epmaxpacketout[b] = ep[e].wMaxPacketSize; - } - else { - if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b]) - dev->epmaxpacketin [b] = ep[e].wMaxPacketSize; - } - } - } -} - -/** - * usb_clear_halt - tells device to clear endpoint halt/stall condition - * @dev: device whose endpoint is halted - * @pipe: endpoint "pipe" being cleared - * Context: !in_interrupt () - * - * This is used to clear halt conditions for bulk and interrupt endpoints, - * as reported by URB completion status. Endpoints that are halted are - * sometimes referred to as being "stalled". Such endpoints are unable - * to transmit or receive data until the halt status is cleared. Any URBs - * queued queued for such an endpoint should normally be unlinked before - * clearing the halt condition. - * - * Note that control and isochronous endpoints don't halt, although control - * endpoints report "protocol stall" (for unsupported requests) using the - * same status code used to report a true stall. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns zero on success, or else the status code returned by the - * underlying usb_control_msg() call. - */ -int usb_clear_halt(struct usb_device *dev, int pipe) -{ - int result; - __u16 status; - unsigned char *buffer; - int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7); - -/* - if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp))) - return 0; -*/ - - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, - HZ * USB_CTRL_SET_TIMEOUT); - - /* don't clear if failed */ - if (result < 0) - return result; - - buffer = kmalloc(sizeof(status), GFP_KERNEL); - if (!buffer) { - err("unable to allocate memory for configuration descriptors"); - return -ENOMEM; - } - - result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp, - // FIXME USB_CTRL_GET_TIMEOUT, yes? why not usb_get_status() ? - buffer, sizeof(status), HZ * USB_CTRL_SET_TIMEOUT); - - memcpy(&status, buffer, sizeof(status)); - kfree(buffer); - - if (result < 0) - return result; - - if (le16_to_cpu(status) & 1) - return -EPIPE; /* still halted */ - - usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); - - /* toggle is reset on clear */ - - usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); - - return 0; -} - -/** - * usb_set_interface - Makes a particular alternate setting be current - * @dev: the device whose interface is being updated - * @interface: the interface being updated - * @alternate: the setting being chosen. - * Context: !in_interrupt () - * - * This is used to enable data transfers on interfaces that may not - * be enabled by default. Not all devices support such configurability. - * - * Within any given configuration, each interface may have several - * alternative settings. These are often used to control levels of - * bandwidth consumption. For example, the default setting for a high - * speed interrupt endpoint may not send more than about 4KBytes per - * microframe, and isochronous endpoints may never be part of a an - * interface's default setting. To access such bandwidth, alternate - * interface setting must be made current. - * - * Note that in the Linux USB subsystem, bandwidth associated with - * an endpoint in a given alternate setting is not reserved until an - * is submitted that needs that bandwidth. Some other operating systems - * allocate bandwidth early, when a configuration is chosen. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns zero on success, or else the status code returned by the - * underlying usb_control_msg() call. - */ -int usb_set_interface(struct usb_device *dev, int interface, int alternate) -{ - struct usb_interface *iface; - struct usb_interface_descriptor *iface_as; - int i, ret; - - iface = usb_ifnum_to_if(dev, interface); - if (!iface) { - warn("selecting invalid interface %d", interface); - return -EINVAL; - } - - /* 9.4.10 says devices don't need this, if the interface - only has one alternate setting */ - if (iface->num_altsetting == 1) { - dbg("ignoring set_interface for dev %d, iface %d, alt %d", - dev->devnum, interface, alternate); - return 0; - } - - if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate, - interface, NULL, 0, HZ * 5)) < 0) - return ret; - - iface->act_altsetting = alternate; - - /* 9.1.1.5: reset toggles for all endpoints affected by this iface-as - * - * Note: - * Despite EP0 is always present in all interfaces/AS, the list of - * endpoints from the descriptor does not contain EP0. Due to its - * omnipresence one might expect EP0 being considered "affected" by - * any SetInterface request and hence assume toggles need to be reset. - * However, EP0 toggles are re-synced for every individual transfer - * during the SETUP stage - hence EP0 toggles are "don't care" here. - */ - - iface_as = &iface->altsetting[alternate]; - for (i = 0; i < iface_as->bNumEndpoints; i++) { - u8 ep = iface_as->endpoint[i].bEndpointAddress; - - usb_settoggle(dev, ep&USB_ENDPOINT_NUMBER_MASK, usb_endpoint_out(ep), 0); - } - - /* usb_set_maxpacket() sets the maxpacket size for all EP in all - * interfaces but it shouldn't do any harm here: we have changed - * the AS for the requested interface only, hence for unaffected - * interfaces it's just re-application of still-valid values. - */ - usb_set_maxpacket(dev); - return 0; -} - -/** - * usb_set_configuration - Makes a particular device setting be current - * @dev: the device whose configuration is being updated - * @configuration: the configuration being chosen. - * Context: !in_interrupt () - * - * This is used to enable non-default device modes. Not all devices - * support this kind of configurability. By default, configuration - * zero is selected after enumeration; many devices only have a single - * configuration. - * - * USB devices may support one or more configurations, which affect - * power consumption and the functionality available. For example, - * the default configuration is limited to using 100mA of bus power, - * so that when certain device functionality requires more power, - * and the device is bus powered, that functionality will be in some - * non-default device configuration. Other device modes may also be - * reflected as configuration options, such as whether two ISDN - * channels are presented as independent 64Kb/s interfaces or as one - * bonded 128Kb/s interface. - * - * Note that USB has an additional level of device configurability, - * associated with interfaces. That configurability is accessed using - * usb_set_interface(). - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns zero on success, or else the status code returned by the - * underlying usb_control_msg() call. - */ -int usb_set_configuration(struct usb_device *dev, int configuration) -{ - int i, ret; - struct usb_config_descriptor *cp = NULL; - - for (i=0; idescriptor.bNumConfigurations; i++) { - if (dev->config[i].bConfigurationValue == configuration) { - cp = &dev->config[i]; - break; - } - } - if (!cp) { - warn("selecting invalid configuration %d", configuration); - return -EINVAL; - } - - if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_CONFIGURATION, 0, configuration, 0, - NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0) - return ret; - - dev->actconfig = cp; - dev->toggle[0] = 0; - dev->toggle[1] = 0; - usb_set_maxpacket(dev); - - return 0; -} - -// hub-only!! ... and only in reset path, or usb_new_device() -// (used by real hubs and virtual root hubs) -int usb_get_configuration(struct usb_device *dev) -{ - int result; - unsigned int cfgno, length; - unsigned char *buffer; - unsigned char *bigbuffer; - struct usb_config_descriptor *desc; - - if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { - warn("too many configurations"); - return -EINVAL; - } - - if (dev->descriptor.bNumConfigurations < 1) { - warn("not enough configurations"); - return -EINVAL; - } - - dev->config = (struct usb_config_descriptor *) - kmalloc(dev->descriptor.bNumConfigurations * - sizeof(struct usb_config_descriptor), GFP_KERNEL); - if (!dev->config) { - err("out of memory"); - return -ENOMEM; - } - memset(dev->config, 0, dev->descriptor.bNumConfigurations * - sizeof(struct usb_config_descriptor)); - - dev->rawdescriptors = (char **)kmalloc(sizeof(char *) * - dev->descriptor.bNumConfigurations, GFP_KERNEL); - if (!dev->rawdescriptors) { - err("out of memory"); - return -ENOMEM; - } - - buffer = kmalloc(8, GFP_KERNEL); - if (!buffer) { - err("unable to allocate memory for configuration descriptors"); - return -ENOMEM; - } - desc = (struct usb_config_descriptor *)buffer; - - for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) { - /* We grab the first 8 bytes so we know how long the whole */ - /* configuration is */ - result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8); - if (result < 8) { - if (result < 0) - err("unable to get descriptor"); - else { - err("config descriptor too short (expected %i, got %i)", 8, result); - result = -EINVAL; - } - goto err; - } - - /* Get the full buffer */ - length = le16_to_cpu(desc->wTotalLength); - - bigbuffer = kmalloc(length, GFP_KERNEL); - if (!bigbuffer) { - err("unable to allocate memory for configuration descriptors"); - result = -ENOMEM; - goto err; - } - - /* Now that we know the length, get the whole thing */ - result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); - if (result < 0) { - err("couldn't get all of config descriptors"); - kfree(bigbuffer); - goto err; - } - - if (result < length) { - err("config descriptor too short (expected %i, got %i)", length, result); - result = -EINVAL; - kfree(bigbuffer); - goto err; - } - - dev->rawdescriptors[cfgno] = bigbuffer; - - result = usb_parse_configuration(&dev->config[cfgno], bigbuffer); - if (result > 0) - dbg("descriptor data left"); - else if (result < 0) { - result = -EINVAL; - goto err; - } - } - - kfree(buffer); - return 0; -err: - kfree(buffer); - dev->descriptor.bNumConfigurations = cfgno; - return result; -} - -/** - * usb_string - returns ISO 8859-1 version of a string descriptor - * @dev: the device whose string descriptor is being retrieved - * @index: the number of the descriptor - * @buf: where to put the string - * @size: how big is "buf"? - * Context: !in_interrupt () - * - * This converts the UTF-16LE encoded strings returned by devices, from - * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones - * that are more usable in most kernel contexts. Note that all characters - * in the chosen descriptor that can't be encoded using ISO-8859-1 - * are converted to the question mark ("?") character, and this function - * chooses strings in the first language supported by the device. - * - * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit - * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode, - * and is appropriate for use many uses of English and several other - * Western European languages. (But it doesn't include the "Euro" symbol.) - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns length of the string (>= 0) or usb_control_msg status (< 0). - */ -int usb_string(struct usb_device *dev, int index, char *buf, size_t size) -{ - unsigned char *tbuf; - int err; - unsigned int u, idx; - - if (size <= 0 || !buf || !index) - return -EINVAL; - buf[0] = 0; - tbuf = kmalloc(256, GFP_KERNEL); - if (!tbuf) - return -ENOMEM; - - /* get langid for strings if it's not yet known */ - if (!dev->have_langid) { - err = usb_get_string(dev, 0, 0, tbuf, 4); - if (err < 0) { - err("error getting string descriptor 0 (error=%d)", err); - goto errout; - } else if (tbuf[0] < 4) { - err("string descriptor 0 too short"); - err = -EINVAL; - goto errout; - } else { - dev->have_langid = -1; - dev->string_langid = tbuf[2] | (tbuf[3]<< 8); - /* always use the first langid listed */ - dbg("USB device number %d default language ID 0x%x", - dev->devnum, dev->string_langid); - } - } - - /* - * Just ask for a maximum length string and then take the length - * that was returned. - */ - err = usb_get_string(dev, dev->string_langid, index, tbuf, 255); - if (err < 0) - goto errout; - - size--; /* leave room for trailing NULL char in output buffer */ - for (idx = 0, u = 2; u < err; u += 2) { - if (idx >= size) - break; - if (tbuf[u+1]) /* high byte */ - buf[idx++] = '?'; /* non ISO-8859-1 character */ - else - buf[idx++] = tbuf[u]; - } - buf[idx] = 0; - err = idx; - - errout: - kfree(tbuf); - return err; -} /* * By the time we get here, the device has gotten a new device ID @@ -2757,12 +1419,16 @@ } #endif +struct bus_type usb_bus_type = { + name: "usb", +}; /* * Init */ static int __init usb_init(void) { + bus_register(&usb_bus_type); usb_major_init(); usbfs_init(); usb_hub_init(); @@ -2775,6 +1441,7 @@ */ static void __exit usb_exit(void) { + put_bus(&usb_bus_type); usb_major_cleanup(); usbfs_cleanup(); usb_hub_cleanup(); @@ -2821,26 +1488,6 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor); EXPORT_SYMBOL(usb_get_current_frame_number); - -// asynchronous request completion model -EXPORT_SYMBOL(usb_alloc_urb); -EXPORT_SYMBOL(usb_free_urb); -EXPORT_SYMBOL(usb_get_urb); -EXPORT_SYMBOL(usb_submit_urb); -EXPORT_SYMBOL(usb_unlink_urb); - -// synchronous request completion model -EXPORT_SYMBOL(usb_control_msg); -EXPORT_SYMBOL(usb_bulk_msg); -// synchronous control message convenience routines -EXPORT_SYMBOL(usb_get_descriptor); -EXPORT_SYMBOL(usb_get_device_descriptor); -EXPORT_SYMBOL(usb_get_status); -EXPORT_SYMBOL(usb_get_string); -EXPORT_SYMBOL(usb_string); -EXPORT_SYMBOL(usb_clear_halt); -EXPORT_SYMBOL(usb_set_configuration); -EXPORT_SYMBOL(usb_set_interface); EXPORT_SYMBOL(usb_devfs_handle); MODULE_LICENSE("GPL"); diff -Nru a/drivers/usb/host/Config.in b/drivers/usb/host/Config.in --- a/drivers/usb/host/Config.in Sun Jun 2 18:44:56 2002 +++ b/drivers/usb/host/Config.in Sun Jun 2 18:44:56 2002 @@ -20,5 +20,6 @@ #fi #dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB if [ "$CONFIG_ARM" = "y" ]; then + dep_tristate ' SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB dep_tristate ' SL811HS support' CONFIG_USB_SL811HS $CONFIG_USB fi diff -Nru a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile --- a/drivers/usb/host/Makefile Sun Jun 2 18:44:58 2002 +++ b/drivers/usb/host/Makefile Sun Jun 2 18:44:58 2002 @@ -3,6 +3,8 @@ # framework and drivers # +export-objs := usb-ohci.o + obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_UHCI_HCD) += usb-uhci-hcd.o @@ -10,7 +12,8 @@ obj-$(CONFIG_USB_UHCI) += usb-uhci.o obj-$(CONFIG_USB_UHCI_ALT) += uhci.o -obj-$(CONFIG_USB_OHCI) += usb-ohci.o +obj-$(CONFIG_USB_OHCI) += usb-ohci.o usb-ohci-pci.o +obj-$(CONFIG_USB_OHCI_SA1111) += usb-ohci.o usb-ohci-sa1111.o obj-$(CONFIG_USB_SL811HS) += hc_sl811.o include $(TOPDIR)/Rules.make diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c --- a/drivers/usb/host/ehci-q.c Sun Jun 2 18:44:56 2002 +++ b/drivers/usb/host/ehci-q.c Sun Jun 2 18:44:56 2002 @@ -144,11 +144,13 @@ usb_pipeendpoint (pipe), usb_pipeout (pipe)); if (urb->dev->tt && !usb_pipeint (pipe)) { +#ifdef DEBUG struct usb_device *tt = urb->dev->tt->hub; dbg ("clear tt %s-%s p%d buffer, a%d ep%d", tt->bus->bus_name, tt->devpath, urb->dev->ttport, urb->dev->devnum, usb_pipeendpoint (pipe)); +#endif /* DEBUG */ usb_hub_tt_clear_buffer (urb->dev, pipe); } } diff -Nru a/drivers/usb/host/usb-ohci-pci.c b/drivers/usb/host/usb-ohci-pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/host/usb-ohci-pci.c Sun Jun 2 18:44:58 2002 @@ -0,0 +1,445 @@ +#include +#include +#include +#include +#include +#include +#include +#include /* for in_interrupt() */ +#undef DEBUG +#include + +#include "../core/hcd.h" +#include "usb-ohci.h" + +#ifdef CONFIG_PMAC_PBOOK +#include +#include +#include +#ifndef CONFIG_PM +#define CONFIG_PM +#endif +#endif + + +/*-------------------------------------------------------------------------*/ + +/* Increment the module usage count, start the control thread and + * return success. */ + +static struct pci_driver ohci_pci_driver; + +static int __devinit +hc_found_ohci (struct pci_dev *dev, int irq, + void *mem_base, const struct pci_device_id *id) +{ + u8 latency, limit; + ohci_t * ohci; + int ret; + + printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name); + + /* bad pci latencies can contribute to overruns */ + pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency); + if (latency) { + pci_read_config_byte (dev, PCI_MAX_LAT, &limit); + if (limit && limit < latency) { + dbg ("PCI latency reduced to max %d", limit); + pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit); + latency = limit; + } + } + + ret = hc_add_ohci(dev, irq, mem_base, id->driver_data, + &ohci, ohci_pci_driver.name, dev->slot_name); + + if (ret == 0) { + ohci->pci_latency = latency; + + if (hc_start (ohci, &ohci->ohci_dev->dev) < 0) { + err ("can't start usb-%s", ohci->slot_name); + hc_remove_ohci(ohci); + return -EBUSY; + } + +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif + } + + return ret; +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_PM + +/* controller died; cleanup debris, then restart */ +/* must not be called from interrupt context */ + +static void hc_restart (ohci_t *ohci) +{ + int temp; + int i; + + if (ohci->pci_latency) + pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency); + + ohci->disabled = 1; + ohci->sleeping = 0; + if (ohci->bus->root_hub) + usb_disconnect (&ohci->bus->root_hub); + + /* empty the interrupt branches */ + for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0; + for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0; + + /* no EDs to remove */ + ohci->ed_rm_list [0] = NULL; + ohci->ed_rm_list [1] = NULL; + + /* empty control and bulk lists */ + ohci->ed_isotail = NULL; + ohci->ed_controltail = NULL; + ohci->ed_bulktail = NULL; + + if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) { + err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp); + } else + dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name); +} + +#endif /* CONFIG_PM */ + +/*-------------------------------------------------------------------------*/ + +/* configured so that an OHCI device is always provided */ +/* always called with process context; sleeping is OK */ + +static int __devinit +ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) +{ + unsigned long mem_resource, mem_len; + void *mem_base; + int status; + + if (pci_enable_device(dev) < 0) + return -ENODEV; + + if (!dev->irq) { + err("found OHCI device with no IRQ assigned. check BIOS settings!"); + pci_disable_device (dev); + return -ENODEV; + } + + /* we read its hardware registers as memory */ + mem_resource = pci_resource_start(dev, 0); + mem_len = pci_resource_len(dev, 0); + if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) { + dbg ("controller already in use"); + pci_disable_device (dev); + return -EBUSY; + } + + mem_base = ioremap_nocache (mem_resource, mem_len); + if (!mem_base) { + err("Error mapping OHCI memory"); + release_mem_region(mem_resource, mem_len); + pci_disable_device (dev); + return -EFAULT; + } + + /* controller writes into our memory */ + pci_set_master (dev); + + status = hc_found_ohci (dev, dev->irq, mem_base, id); + if (status < 0) { + iounmap (mem_base); + release_mem_region(mem_resource, mem_len); + pci_disable_device (dev); + } + return status; +} + +/*-------------------------------------------------------------------------*/ + +/* may be called from interrupt context [interface spec] */ +/* may be called without controller present */ +/* may be called with controller, bus, and devices active */ + +static void __devexit +ohci_pci_remove (struct pci_dev *dev) +{ + ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev); + + dbg ("remove %s controller usb-%s%s%s", + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), + dev->slot_name, + ohci->disabled ? " (disabled)" : "", + in_interrupt () ? " in interrupt" : "" + ); + + hc_remove_ohci(ohci); + + release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0)); +} + + +#ifdef CONFIG_PM + +/*-------------------------------------------------------------------------*/ + +static int +ohci_pci_suspend (struct pci_dev *dev, u32 state) +{ + ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev); + unsigned long flags; + u16 cmd; + + if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { + dbg ("can't suspend usb-%s (state is %s)", dev->slot_name, + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); + return -EIO; + } + + /* act as if usb suspend can always be used */ + info ("USB suspend: usb-%s", dev->slot_name); + ohci->sleeping = 1; + + /* First stop processing */ + spin_lock_irqsave (&usb_ed_lock, flags); + ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); + writel (ohci->hc_control, &ohci->regs->control); + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + (void) readl (&ohci->regs->intrstatus); + spin_unlock_irqrestore (&usb_ed_lock, flags); + + /* Wait a frame or two */ + mdelay(1); + if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) + mdelay (1); + +#ifdef CONFIG_PMAC_PBOOK + if (_machine == _MACH_Pmac) + disable_irq (ohci->irq); + /* else, 2.4 assumes shared irqs -- don't disable */ +#endif + /* Enable remote wakeup */ + writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable); + + /* Suspend chip and let things settle down a bit */ + ohci->hc_control = OHCI_USB_SUSPEND; + writel (ohci->hc_control, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (500); /* No schedule here ! */ + switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) { + case OHCI_USB_RESET: + dbg("Bus in reset phase ???"); + break; + case OHCI_USB_RESUME: + dbg("Bus in resume phase ???"); + break; + case OHCI_USB_OPER: + dbg("Bus in operational phase ???"); + break; + case OHCI_USB_SUSPEND: + dbg("Bus suspended"); + break; + } + /* In some rare situations, Apple's OHCI have happily trashed + * memory during sleep. We disable it's bus master bit during + * suspend + */ + pci_read_config_word (dev, PCI_COMMAND, &cmd); + cmd &= ~PCI_COMMAND_MASTER; + pci_write_config_word (dev, PCI_COMMAND, cmd); +#ifdef CONFIG_PMAC_PBOOK + { + struct device_node *of_node; + + /* Disable USB PAD & cell clock */ + of_node = pci_device_to_OF_node (ohci->ohci_dev); + if (of_node && _machine == _MACH_Pmac) + pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); + } +#endif + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static int +ohci_pci_resume (struct pci_dev *dev) +{ + ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev); + int temp; + unsigned long flags; + + /* guard against multiple resumes */ + atomic_inc (&ohci->resume_count); + if (atomic_read (&ohci->resume_count) != 1) { + err ("concurrent PCI resumes for usb-%s", dev->slot_name); + atomic_dec (&ohci->resume_count); + return 0; + } + +#ifdef CONFIG_PMAC_PBOOK + { + struct device_node *of_node; + + /* Re-enable USB PAD & cell clock */ + of_node = pci_device_to_OF_node (ohci->ohci_dev); + if (of_node && _machine == _MACH_Pmac) + pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1); + } +#endif + + /* did we suspend, or were we powered off? */ + ohci->hc_control = readl (&ohci->regs->control); + temp = ohci->hc_control & OHCI_CTRL_HCFS; + +#ifdef DEBUG + /* the registers may look crazy here */ + ohci_dump_status (ohci); +#endif + + /* Re-enable bus mastering */ + pci_set_master(ohci->ohci_dev); + + switch (temp) { + + case OHCI_USB_RESET: // lost power + info ("USB restart: usb-%s", dev->slot_name); + hc_restart (ohci); + break; + + case OHCI_USB_SUSPEND: // host wakeup + case OHCI_USB_RESUME: // remote wakeup + info ("USB continue: usb-%s from %s wakeup", dev->slot_name, + (temp == OHCI_USB_SUSPEND) + ? "host" : "remote"); + ohci->hc_control = OHCI_USB_RESUME; + writel (ohci->hc_control, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (20); /* no schedule here ! */ + /* Some controllers (lucent) need a longer delay here */ + mdelay (15); + temp = readl (&ohci->regs->control); + temp = ohci->hc_control & OHCI_CTRL_HCFS; + if (temp != OHCI_USB_RESUME) { + err ("controller usb-%s won't resume", dev->slot_name); + ohci->disabled = 1; + return -EIO; + } + + /* Some chips likes being resumed first */ + writel (OHCI_USB_OPER, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (3); + + /* Then re-enable operations */ + spin_lock_irqsave (&usb_ed_lock, flags); + ohci->disabled = 0; + ohci->sleeping = 0; + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) { + if (ohci->ed_controltail) + ohci->hc_control |= OHCI_CTRL_CLE; + if (ohci->ed_bulktail) + ohci->hc_control |= OHCI_CTRL_BLE; + } + writel (ohci->hc_control, &ohci->regs->control); + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + writel (OHCI_INTR_SF, &ohci->regs->intrenable); + /* Check for a pending done list */ + writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); + (void) readl (&ohci->regs->intrdisable); + spin_unlock_irqrestore (&usb_ed_lock, flags); +#ifdef CONFIG_PMAC_PBOOK + if (_machine == _MACH_Pmac) + enable_irq (ohci->irq); +#endif + if (ohci->hcca->done_head) + dl_done_list (ohci, dl_reverse_done_list (ohci)); + writel (OHCI_INTR_WDH, &ohci->regs->intrenable); + writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ + writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ + break; + + default: + warn ("odd PCI resume for usb-%s", dev->slot_name); + } + + /* controller is operational, extra resumes are harmless */ + atomic_dec (&ohci->resume_count); + + return 0; +} + +#endif /* CONFIG_PM */ + + +/*-------------------------------------------------------------------------*/ + +static const struct pci_device_id __devinitdata ohci_pci_ids [] = { { + + /* + * AMD-756 [Viper] USB has a serious erratum when used with + * lowspeed devices like mice. + */ + vendor: 0x1022, + device: 0x740c, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + + driver_data: OHCI_QUIRK_AMD756, + +} , { + + /* handle any USB OHCI controller */ + class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10), + class_mask: ~0, + + /* no matter who makes it */ + vendor: PCI_ANY_ID, + device: PCI_ANY_ID, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + + }, { /* end: all zeroes */ } +}; + +MODULE_DEVICE_TABLE (pci, ohci_pci_ids); + +static struct pci_driver ohci_pci_driver = { + name: "usb-ohci", + id_table: &ohci_pci_ids [0], + + probe: ohci_pci_probe, + remove: __devexit_p(ohci_pci_remove), + +#ifdef CONFIG_PM + suspend: ohci_pci_suspend, + resume: ohci_pci_resume, +#endif /* PM */ +}; + + +/*-------------------------------------------------------------------------*/ + +static int __init ohci_hcd_init (void) +{ + return pci_module_init (&ohci_pci_driver); +} + +/*-------------------------------------------------------------------------*/ + +static void __exit ohci_hcd_cleanup (void) +{ + pci_unregister_driver (&ohci_pci_driver); +} + +module_init (ohci_hcd_init); +module_exit (ohci_hcd_cleanup); + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/usb/host/usb-ohci-sa1111.c b/drivers/usb/host/usb-ohci-sa1111.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/host/usb-ohci-sa1111.c Sun Jun 2 18:44:58 2002 @@ -0,0 +1,130 @@ +/* + * linux/drivers/usb/usb-ohci-sa1111.c + * + * The outline of this code was taken from Brad Parkers + * original OHCI driver modifications, and reworked into a cleaner form + * by Russell King . + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "usb-ohci.h" + +int __devinit +hc_add_ohci(struct pci_dev *dev, int irq, void *membase, unsigned long flags, + ohci_t **ohci, const char *name, const char *slot_name); +extern void hc_remove_ohci(ohci_t *ohci); + +static ohci_t *sa1111_ohci; + +static void __init sa1111_ohci_configure(void) +{ + unsigned int usb_rst = 0; + + if (machine_is_xp860() || + machine_has_neponset() || + machine_is_pfs168() || + machine_is_badge4()) + usb_rst = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW; + + /* + * Configure the power sense and control lines. Place the USB + * host controller in reset. + */ + USB_RESET = usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET; + + /* + * Now, carefully enable the USB clock, and take + * the USB host controller out of reset. + */ + SKPCR |= SKPCR_UCLKEN; + udelay(11); + USB_RESET = usb_rst; +} + +static int __init sa1111_ohci_init(void) +{ + int ret; + + if (!sa1111) + return -ENODEV; + + /* + * Request memory resources. + */ +// if (!request_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT, "usb-ohci")) +// return -EBUSY; + + sa1111_ohci_configure(); + + /* + * Initialise the generic OHCI driver. + */ + ret = hc_add_ohci((struct pci_dev *)1, NIRQHCIM, + (void *)&USB_OHCI_OP_BASE, 0, &sa1111_ohci, + "usb-ohci", "sa1111"); + + if (ret == 0) { + if (hc_start (sa1111_ohci, &sa1111->dev) < 0) { + err ("can't start usb-%s", sa1111_ohci->slot_name); + hc_remove_ohci (sa1111_ohci); + return -EBUSY; + } + +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif +#ifdef CONFIG_SA1100_BADGE4 + if (machine_is_badge4()) { + /* found the controller, so now power the bus */ + badge4_set_5V(BADGE4_5V_USB, 1); + } +#endif + } +// else +// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT); + + return ret; +} + +static void __exit sa1111_ohci_exit(void) +{ + hc_remove_ohci(sa1111_ohci); + + /* + * Put the USB host controller into reset. + */ + USB_RESET |= USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET; + + /* + * Stop the USB clock. + */ + SKPCR &= ~SKPCR_UCLKEN; + + /* + * Release memory resources. + */ +// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT); + +#ifdef CONFIG_SA1100_BADGE4 + if (machine_is_badge4()) { + badge4_set_5V(BADGE4_5V_USB, 0); + } +#endif +} + +module_init(sa1111_ohci_init); +module_exit(sa1111_ohci_exit); diff -Nru a/drivers/usb/host/usb-ohci.c b/drivers/usb/host/usb-ohci.c --- a/drivers/usb/host/usb-ohci.c Sun Jun 2 18:44:56 2002 +++ b/drivers/usb/host/usb-ohci.c Sun Jun 2 18:44:56 2002 @@ -82,16 +82,6 @@ #include "usb-ohci.h" -#ifdef CONFIG_PMAC_PBOOK -#include -#include -#include -#ifndef CONFIG_PM -#define CONFIG_PM -#endif -#endif - - /* * Version Information */ @@ -99,14 +89,10 @@ #define DRIVER_AUTHOR "Roman Weissgaerber , David Brownell" #define DRIVER_DESC "USB OHCI Host Controller Driver" -/* For initializing controller (mask in an HCFS mode too) */ -#define OHCI_CONTROL_INIT \ - (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE - #define OHCI_UNLINK_TIMEOUT (HZ / 10) static LIST_HEAD (ohci_hcd_list); -static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED; +spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED; /*-------------------------------------------------------------------------*/ @@ -443,7 +429,7 @@ static void ohci_dump (ohci_t *controller, int verbose) { - dbg ("OHCI controller usb-%s state", controller->ohci_dev->slot_name); + dbg ("OHCI controller usb-%s state", controller->slot_name); // dumps some of the state we know about ohci_dump_status (controller); @@ -465,7 +451,7 @@ static int sohci_return_urb (struct ohci *hc, struct urb * urb) { urb_priv_t * urb_priv = urb->hcpriv; - struct urb * urbt; + struct urb * urbt = NULL; unsigned long flags; int i; @@ -499,7 +485,7 @@ break; case PIPE_ISOCHRONOUS: - for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next); + // for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next); if (urbt) { /* send the reply and requeue URB */ pci_unmap_single (hc->ohci_dev, urb_priv->td [0]->data_dma, @@ -865,7 +851,7 @@ if (ed->state == ED_OPER) { /* driver on that interface didn't unlink an urb */ dbg ("driver usb-%s dev %d ed 0x%x unfreed URB", - ohci->ohci_dev->slot_name, usb_dev->devnum, i); + ohci->slot_name, usb_dev->devnum, i); ep_unlink (ohci, ed); } ep_rm_ed (usb_dev, ed); @@ -910,7 +896,7 @@ } else { /* likely some interface's driver has a refcount bug */ err ("bus %s devnum %d deletion in interrupt", - ohci->ohci_dev->slot_name, usb_dev->devnum); + ohci->slot_name, usb_dev->devnum); BUG (); } } @@ -1529,7 +1515,7 @@ /* replies to the request have to be on a FIFO basis so * we reverse the reversed done-list */ -static td_t * dl_reverse_done_list (ohci_t * ohci) +td_t * dl_reverse_done_list (ohci_t * ohci) { __u32 td_list_hc; td_t * td_rev = NULL; @@ -1677,7 +1663,7 @@ /* td done list */ -static void dl_done_list (ohci_t * ohci, td_t * td_list) +void dl_done_list (ohci_t * ohci, td_t * td_list) { td_t * td_list_next = NULL; ed_t * ed; @@ -1822,7 +1808,7 @@ num_ports = roothub_a (ohci) & RH_A_NDP; if (num_ports > MAX_ROOT_PORTS) { err ("bogus NDP=%d for OHCI usb-%s", num_ports, - ohci->ohci_dev->slot_name); + ohci->slot_name); err ("rereads as NDP=%d", readl (&ohci->regs->roothub.a) & RH_A_NDP); /* retry later; "should not happen" */ @@ -2148,7 +2134,7 @@ /* reset the HC and BUS */ -static int hc_reset (ohci_t * ohci) +int hc_reset (ohci_t * ohci) { int timeout = 30; int smm_timeout = 50; /* 0,5 sec */ @@ -2169,7 +2155,7 @@ writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); dbg("USB HC reset_hc usb-%s: ctrl = 0x%x ;", - ohci->ohci_dev->slot_name, + ohci->slot_name, readl (&ohci->regs->control)); /* Reset USB (needed by some controllers) */ @@ -2193,7 +2179,7 @@ * enable interrupts * connect the virtual root hub */ -static int hc_start (ohci_t * ohci) +int hc_start (ohci_t * ohci, struct device *parent_dev) { __u32 mask; unsigned int fminterval; @@ -2247,7 +2233,7 @@ dev = usb_to_ohci (usb_dev); ohci->bus->root_hub = usb_dev; usb_connect (usb_dev); - if (usb_register_root_hub (usb_dev, &ohci->ohci_dev->dev) != 0) { + if (usb_register_root_hub (usb_dev, parent_dev) != 0) { usb_free_dev (usb_dev); ohci->disabled = 1; return -ENODEV; @@ -2308,7 +2294,7 @@ if (ints & OHCI_INTR_UE) { ohci->disabled++; err ("OHCI Unrecoverable Error, controller usb-%s disabled", - ohci->ohci_dev->slot_name); + ohci->slot_name); // e.g. due to PCI Master/Target Abort #ifdef DEBUG @@ -2385,7 +2371,9 @@ ohci->regs = mem_base; ohci->ohci_dev = dev; +#ifdef CONFIG_PCI pci_set_drvdata(dev, ohci); +#endif INIT_LIST_HEAD (&ohci->ohci_hcd_list); list_add (&ohci->ohci_hcd_list, &ohci_hcd_list); @@ -2394,7 +2382,9 @@ ohci->bus = usb_alloc_bus (&sohci_device_operations); if (!ohci->bus) { +#ifdef CONFIG_PCI pci_set_drvdata (dev, NULL); +#endif pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca, ohci->hcca, ohci->hcca_dma); kfree (ohci); @@ -2413,7 +2403,7 @@ static void hc_release_ohci (ohci_t * ohci) { - dbg ("USB HC release ohci usb-%s", ohci->ohci_dev->slot_name); + dbg ("USB HC release ohci usb-%s", ohci->slot_name); /* disconnect all devices */ if (ohci->bus->root_hub) @@ -2426,7 +2416,9 @@ free_irq (ohci->irq, ohci); ohci->irq = -1; } +#ifdef CONFIG_PCI pci_set_drvdata(ohci->ohci_dev, NULL); +#endif if (ohci->bus) { if (ohci->bus->busnum) usb_deregister_bus (ohci->bus); @@ -2448,18 +2440,15 @@ /*-------------------------------------------------------------------------*/ -/* Increment the module usage count, start the control thread and - * return success. */ - -static struct pci_driver ohci_pci_driver; - -static int __devinit -hc_found_ohci (struct pci_dev *dev, int irq, - void *mem_base, const struct pci_device_id *id) +/* + * Host bus independent add one OHCI host controller. + */ +int +hc_add_ohci(struct pci_dev *dev, int irq, void *mem_base, unsigned long flags, + ohci_t **ohcip, const char *name, const char *slot_name) { - ohci_t * ohci; - u8 latency, limit; char buf[8], *bufp = buf; + ohci_t * ohci; int ret; #ifndef __sparc__ @@ -2469,34 +2458,20 @@ #endif printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n", (unsigned long) mem_base, bufp); - printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name); ohci = hc_alloc_ohci (dev, mem_base); if (!ohci) { return -ENOMEM; } + ohci->slot_name = slot_name; if ((ret = ohci_mem_init (ohci)) < 0) { hc_release_ohci (ohci); return ret; } - ohci->flags = id->driver_data; + ohci->flags = flags; if (ohci->flags & OHCI_QUIRK_AMD756) printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n"); - /* bad pci latencies can contribute to overruns */ - pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency); - if (latency) { - pci_read_config_byte (dev, PCI_MAX_LAT, &limit); - if (limit && limit < latency) { - dbg ("PCI latency reduced to max %d", limit); - pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit); - ohci->pci_latency = limit; - } else { - /* it might already have been reduced */ - ohci->pci_latency = latency; - } - } - if (hc_reset (ohci) < 0) { hc_release_ohci (ohci); return -ENODEV; @@ -2508,134 +2483,23 @@ usb_register_bus (ohci->bus); - if (request_irq (irq, hc_interrupt, SA_SHIRQ, - ohci_pci_driver.name, ohci) != 0) { + if (request_irq (irq, hc_interrupt, SA_SHIRQ, name, ohci) != 0) { err ("request interrupt %s failed", bufp); hc_release_ohci (ohci); return -EBUSY; } ohci->irq = irq; - if (hc_start (ohci) < 0) { - err ("can't start usb-%s", dev->slot_name); - hc_release_ohci (ohci); - return -EBUSY; - } + *ohcip = ohci; -#ifdef DEBUG - ohci_dump (ohci, 1); -#endif return 0; } -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_PM - -/* controller died; cleanup debris, then restart */ -/* must not be called from interrupt context */ - -static void hc_restart (ohci_t *ohci) -{ - int temp; - int i; - - if (ohci->pci_latency) - pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency); - - ohci->disabled = 1; - ohci->sleeping = 0; - if (ohci->bus->root_hub) - usb_disconnect (&ohci->bus->root_hub); - - /* empty the interrupt branches */ - for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0; - for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0; - - /* no EDs to remove */ - ohci->ed_rm_list [0] = NULL; - ohci->ed_rm_list [1] = NULL; - - /* empty control and bulk lists */ - ohci->ed_isotail = NULL; - ohci->ed_controltail = NULL; - ohci->ed_bulktail = NULL; - - if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) { - err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp); - } else - dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name); -} - -#endif /* CONFIG_PM */ - -/*-------------------------------------------------------------------------*/ - -/* configured so that an OHCI device is always provided */ -/* always called with process context; sleeping is OK */ - -static int __devinit -ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) +/* + * Host bus independent remove one OHCI host controller. + */ +void hc_remove_ohci(ohci_t *ohci) { - unsigned long mem_resource, mem_len; - void *mem_base; - int status; - - if (pci_enable_device(dev) < 0) - return -ENODEV; - - if (!dev->irq) { - err("found OHCI device with no IRQ assigned. check BIOS settings!"); - pci_disable_device (dev); - return -ENODEV; - } - - /* we read its hardware registers as memory */ - mem_resource = pci_resource_start(dev, 0); - mem_len = pci_resource_len(dev, 0); - if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) { - dbg ("controller already in use"); - pci_disable_device (dev); - return -EBUSY; - } - - mem_base = ioremap_nocache (mem_resource, mem_len); - if (!mem_base) { - err("Error mapping OHCI memory"); - release_mem_region (mem_resource, mem_len); - pci_disable_device (dev); - return -EFAULT; - } - - /* controller writes into our memory */ - pci_set_master (dev); - - status = hc_found_ohci (dev, dev->irq, mem_base, id); - if (status < 0) { - iounmap (mem_base); - release_mem_region (mem_resource, mem_len); - pci_disable_device (dev); - } - return status; -} - -/*-------------------------------------------------------------------------*/ - -/* may be called from interrupt context [interface spec] */ -/* may be called without controller present */ -/* may be called with controller, bus, and devices active */ - -static void __devexit -ohci_pci_remove (struct pci_dev *dev) -{ - ohci_t *ohci = pci_get_drvdata(dev); - - dbg ("remove %s controller usb-%s%s%s", - hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), - dev->slot_name, - ohci->disabled ? " (disabled)" : "", - in_interrupt () ? " in interrupt" : "" - ); #ifdef DEBUG ohci_dump (ohci, 1); #endif @@ -2652,270 +2516,16 @@ &ohci->regs->control); hc_release_ohci (ohci); - - release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0)); - pci_disable_device (dev); -} - - -#ifdef CONFIG_PM - -/*-------------------------------------------------------------------------*/ - -static int -ohci_pci_suspend (struct pci_dev *dev, u32 state) -{ - ohci_t *ohci = pci_get_drvdata(dev); - unsigned long flags; - u16 cmd; - - if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { - dbg ("can't suspend usb-%s (state is %s)", dev->slot_name, - hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); - return -EIO; - } - - /* act as if usb suspend can always be used */ - info ("USB suspend: usb-%s", dev->slot_name); - ohci->sleeping = 1; - - /* First stop processing */ - spin_lock_irqsave (&usb_ed_lock, flags); - ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); - writel (ohci->hc_control, &ohci->regs->control); - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); - (void) readl (&ohci->regs->intrstatus); - spin_unlock_irqrestore (&usb_ed_lock, flags); - - /* Wait a frame or two */ - mdelay(1); - if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) - mdelay (1); - -#ifdef CONFIG_PMAC_PBOOK - if (_machine == _MACH_Pmac) - disable_irq (ohci->irq); - /* else, 2.4 assumes shared irqs -- don't disable */ -#endif - /* Enable remote wakeup */ - writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable); - - /* Suspend chip and let things settle down a bit */ - ohci->hc_control = OHCI_USB_SUSPEND; - writel (ohci->hc_control, &ohci->regs->control); - (void) readl (&ohci->regs->control); - mdelay (500); /* No schedule here ! */ - switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) { - case OHCI_USB_RESET: - dbg("Bus in reset phase ???"); - break; - case OHCI_USB_RESUME: - dbg("Bus in resume phase ???"); - break; - case OHCI_USB_OPER: - dbg("Bus in operational phase ???"); - break; - case OHCI_USB_SUSPEND: - dbg("Bus suspended"); - break; - } - /* In some rare situations, Apple's OHCI have happily trashed - * memory during sleep. We disable it's bus master bit during - * suspend - */ - pci_read_config_word (dev, PCI_COMMAND, &cmd); - cmd &= ~PCI_COMMAND_MASTER; - pci_write_config_word (dev, PCI_COMMAND, cmd); -#ifdef CONFIG_PMAC_PBOOK - { - struct device_node *of_node; - - /* Disable USB PAD & cell clock */ - of_node = pci_device_to_OF_node (ohci->ohci_dev); - if (of_node) - pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); - } -#endif - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static int -ohci_pci_resume (struct pci_dev *dev) -{ - ohci_t *ohci = pci_get_drvdata(dev); - int temp; - unsigned long flags; - - /* guard against multiple resumes */ - atomic_inc (&ohci->resume_count); - if (atomic_read (&ohci->resume_count) != 1) { - err ("concurrent PCI resumes for usb-%s", dev->slot_name); - atomic_dec (&ohci->resume_count); - return 0; - } - -#ifdef CONFIG_PMAC_PBOOK - { - struct device_node *of_node; - - /* Re-enable USB PAD & cell clock */ - of_node = pci_device_to_OF_node (ohci->ohci_dev); - if (of_node) - pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1); - } -#endif - - /* did we suspend, or were we powered off? */ - ohci->hc_control = readl (&ohci->regs->control); - temp = ohci->hc_control & OHCI_CTRL_HCFS; - -#ifdef DEBUG - /* the registers may look crazy here */ - ohci_dump_status (ohci); -#endif - - /* Re-enable bus mastering */ - pci_set_master(ohci->ohci_dev); - - switch (temp) { - - case OHCI_USB_RESET: // lost power - info ("USB restart: usb-%s", dev->slot_name); - hc_restart (ohci); - break; - - case OHCI_USB_SUSPEND: // host wakeup - case OHCI_USB_RESUME: // remote wakeup - info ("USB continue: usb-%s from %s wakeup", dev->slot_name, - (temp == OHCI_USB_SUSPEND) - ? "host" : "remote"); - ohci->hc_control = OHCI_USB_RESUME; - writel (ohci->hc_control, &ohci->regs->control); - (void) readl (&ohci->regs->control); - mdelay (20); /* no schedule here ! */ - /* Some controllers (lucent) need a longer delay here */ - mdelay (15); - temp = readl (&ohci->regs->control); - temp = ohci->hc_control & OHCI_CTRL_HCFS; - if (temp != OHCI_USB_RESUME) { - err ("controller usb-%s won't resume", dev->slot_name); - ohci->disabled = 1; - return -EIO; - } - - /* Some chips likes being resumed first */ - writel (OHCI_USB_OPER, &ohci->regs->control); - (void) readl (&ohci->regs->control); - mdelay (3); - - /* Then re-enable operations */ - spin_lock_irqsave (&usb_ed_lock, flags); - ohci->disabled = 0; - ohci->sleeping = 0; - ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; - if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) { - if (ohci->ed_controltail) - ohci->hc_control |= OHCI_CTRL_CLE; - if (ohci->ed_bulktail) - ohci->hc_control |= OHCI_CTRL_BLE; - } - writel (ohci->hc_control, &ohci->regs->control); - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); - writel (OHCI_INTR_SF, &ohci->regs->intrenable); - /* Check for a pending done list */ - writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); - (void) readl (&ohci->regs->intrdisable); - spin_unlock_irqrestore (&usb_ed_lock, flags); -#ifdef CONFIG_PMAC_PBOOK - if (_machine == _MACH_Pmac) - enable_irq (ohci->irq); -#endif - if (ohci->hcca->done_head) - dl_done_list (ohci, dl_reverse_done_list (ohci)); - writel (OHCI_INTR_WDH, &ohci->regs->intrenable); - writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ - writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ - break; - - default: - warn ("odd PCI resume for usb-%s", dev->slot_name); - } - - /* controller is operational, extra resumes are harmless */ - atomic_dec (&ohci->resume_count); - - return 0; -} - -#endif /* CONFIG_PM */ - - -/*-------------------------------------------------------------------------*/ - -static const struct pci_device_id __devinitdata ohci_pci_ids [] = { { - - /* - * AMD-756 [Viper] USB has a serious erratum when used with - * lowspeed devices like mice. - */ - vendor: 0x1022, - device: 0x740c, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - - driver_data: OHCI_QUIRK_AMD756, - -} , { - - /* handle any USB OHCI controller */ - class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10), - class_mask: ~0, - - /* no matter who makes it */ - vendor: PCI_ANY_ID, - device: PCI_ANY_ID, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - - }, { /* end: all zeroes */ } -}; - -MODULE_DEVICE_TABLE (pci, ohci_pci_ids); - -static struct pci_driver ohci_pci_driver = { - name: "usb-ohci", - id_table: &ohci_pci_ids [0], - - probe: ohci_pci_probe, - remove: __devexit_p(ohci_pci_remove), - -#ifdef CONFIG_PM - suspend: ohci_pci_suspend, - resume: ohci_pci_resume, -#endif /* PM */ -}; - - -/*-------------------------------------------------------------------------*/ - -static int __init ohci_hcd_init (void) -{ - return pci_module_init (&ohci_pci_driver); } -/*-------------------------------------------------------------------------*/ - -static void __exit ohci_hcd_cleanup (void) -{ - pci_unregister_driver (&ohci_pci_driver); -} - -module_init (ohci_hcd_init); -module_exit (ohci_hcd_cleanup); - - MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(hc_add_ohci); +EXPORT_SYMBOL(hc_remove_ohci); +EXPORT_SYMBOL(hc_start); +EXPORT_SYMBOL(hc_reset); +EXPORT_SYMBOL(dl_done_list); +EXPORT_SYMBOL(dl_reverse_done_list); +EXPORT_SYMBOL(usb_ed_lock); diff -Nru a/drivers/usb/host/usb-ohci.h b/drivers/usb/host/usb-ohci.h --- a/drivers/usb/host/usb-ohci.h Sun Jun 2 18:44:56 2002 +++ b/drivers/usb/host/usb-ohci.h Sun Jun 2 18:44:56 2002 @@ -403,6 +403,7 @@ /* PCI device handle, settings, ... */ struct pci_dev *ohci_dev; + const char *slot_name; u8 pci_latency; struct pci_pool *td_cache; struct pci_pool *dev_cache; @@ -423,6 +424,10 @@ // #define ohci_to_usb(ohci) ((ohci)->usb) #define usb_to_ohci(usb) ((struct ohci_device *)(usb)->hcpriv) +/* For initializing controller (mask in an HCFS mode too) */ +#define OHCI_CONTROL_INIT \ + (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE + /* hcd */ /* endpoint */ static int ep_link(ohci_t * ohci, ed_t * ed); @@ -447,11 +452,6 @@ # define OHCI_MEM_FLAGS 0 #endif -#ifndef CONFIG_PCI -# error "usb-ohci currently requires PCI-based controllers" - /* to support non-PCI OHCIs, you need custom bus/mem/... glue */ -#endif - /* Recover a TD/ED using its collision chain */ static void * @@ -640,4 +640,9 @@ { pci_pool_free (hc->dev_cache, dev, dev->dma); } + +extern spinlock_t usb_ed_lock; +extern void dl_done_list (ohci_t * ohci, td_t * td_list); +extern td_t * dl_reverse_done_list (ohci_t * ohci); + diff -Nru a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c --- a/drivers/usb/image/scanner.c Sun Jun 2 18:44:57 2002 +++ b/drivers/usb/image/scanner.c Sun Jun 2 18:44:57 2002 @@ -1,13 +1,13 @@ /* -*- linux-c -*- */ /* - * Driver for USB Scanners (linux-2.4.12) + * Driver for USB Scanners (linux-2.4.18) * - * Copyright (C) 1999, 2000, 2001 David E. Nelson + * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson * * Portions may be copyright Brad Keryan and Michael Gee. * - * David E. Nelson (dnelson@jump.net) + * Brian Beattie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -302,11 +302,24 @@ * * 05/21/02 Currently maintained by Brian Beattie * + * 0.4.8 5/30/2002 + * - Added Mustek BearPaw 2400 TA. Thanks to Sergey + * Vlasov . + * - Added Mustek 1200UB Plus and Mustek BearPaw 1200 CU ID's. These use + * the Grandtech GT-6801 chip. Thanks to Henning + * Meier-Geinitz . + * - Increased Epson timeout to 60 secs as requested from + * Karl Heinz Kremer . + * - Changed maintainership from David E. Nelson to Brian + * Beattie . + * * TODO + * - Remove the 2/3 endpoint limitation * - Performance * - Select/poll methods * - More testing * - Proper registry/assignment for LM9830 ioctl's + * - More general usage ioctl's * * * Thanks to: @@ -322,6 +335,8 @@ * - All the folks who chimed in with reports and suggestions. * - All the developers that are working on USB SANE backends or other * applications to use USB scanners. + * - Thanks to Greg KH for setting up Brian Beattie + * to be the new USB Scanner maintainer. * * Performance: * @@ -1035,7 +1050,7 @@ switch (dev->descriptor.idVendor) { /* Scanner specific read timeout parameters */ case 0x04b8: /* Seiko/Epson */ - scn->rd_nak_timeout = HZ * 40; + scn->rd_nak_timeout = HZ * 60; break; case 0x055f: /* Mustek */ case 0x0400: /* Another Mustek */ diff -Nru a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h --- a/drivers/usb/image/scanner.h Sun Jun 2 18:44:57 2002 +++ b/drivers/usb/image/scanner.h Sun Jun 2 18:44:57 2002 @@ -1,9 +1,9 @@ /* - * Driver for USB Scanners (linux-2.4.12) + * Driver for USB Scanners (linux-2.4.18) * - * Copyright (C) 1999, 2000, 2001 David E. Nelson + * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson * - * David E. Nelson (dnelson@jump.net) + * Brian Beattie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -51,7 +51,7 @@ static __s32 vendor=-1, product=-1, read_timeout=0; -MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson"); +MODULE_AUTHOR("Brian Beattie, beattie@beattie-home.net"); MODULE_DESCRIPTION(DRIVER_DESC" "DRIVER_VERSION); MODULE_LICENSE("GPL"); @@ -144,6 +144,8 @@ { USB_DEVICE(0x0400, 0x1001) }, /* BearPaw 2400 */ { USB_DEVICE(0x055f, 0x0008) }, /* 1200 CU Plus */ { USB_DEVICE(0x0ff5, 0x0010) }, /* BearPaw 1200F */ + { USB_DEVICE(0x055f, 0x0218) }, /* BearPaw 2400 TA */ + { USB_DEVICE(0x05d8, 0x4002) }, /* 1200 CU and 1200 UB Plus */ /* Plustek */ { USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12 */ { USB_DEVICE(0x07b3, 0x0011) }, /* OpticPro UT24 */ diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c --- a/drivers/usb/storage/freecom.c Sun Jun 2 18:44:57 2002 +++ b/drivers/usb/storage/freecom.c Sun Jun 2 18:44:57 2002 @@ -167,108 +167,6 @@ srb->result = result; } -#if 0 -/* Write a value to an ide register. */ -static int -freecom_ide_write (struct us_data *us, int reg, int value) -{ - freecom_udata_t extra = (freecom_udata_t) us->extra; - struct freecom_ide_out *ideout = - (struct freecom_ide_out *) extra->buffer; - int opipe; - int result, partial; - - US_DEBUGP("IDE out 0x%02x <- 0x%02x\n", reg, value); - - /* Get handles for both transports. */ - opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out); - - if (reg < 0 || reg > 8) - return USB_STOR_TRANSPORT_ERROR; - if (reg < 8) - reg |= 0x20; - else - reg = 0x0e; - - ideout->Type = FCM_PACKET_IDE_WRITE | reg; - ideout->Pad = 0; - ideout->Value = cpu_to_le16 (value); - memset (ideout->Pad2, 0, sizeof (ideout->Pad2)); - - result = usb_stor_bulk_msg (us, ideout, opipe, - FCM_PACKET_LENGTH, &partial); - if (result != 0) { - if (result == -ENOENT) - return US_BULK_TRANSFER_ABORTED; - else - return USB_STOR_TRANSPORT_ERROR; - } - - return USB_STOR_TRANSPORT_GOOD; -} - -/* Read a value from an ide register. */ -static int -freecom_ide_read (struct us_data *us, int reg, int *value) -{ - freecom_udata_t extra = (freecom_udata_t) us->extra; - struct freecom_ide_in *idein = - (struct freecom_ide_in *) extra->buffer; - __u8 *buffer = extra->buffer; - int ipipe, opipe; - int result, partial; - int desired_length; - - /* Get handles for both transports. */ - opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out); - ipipe = usb_rcvbulkpipe (us->pusb_dev, us->ep_in); - - if (reg < 0 || reg > 8) - return USB_STOR_TRANSPORT_ERROR; - if (reg < 8) - reg |= 0x10; - else - reg = 0x0e; - - US_DEBUGP("IDE in request for register 0x%02x\n", reg); - - idein->Type = FCM_PACKET_IDE_READ | reg; - memset (idein->Pad, 0, sizeof (idein->Pad)); - - result = usb_stor_bulk_msg (us, idein, opipe, - FCM_PACKET_LENGTH, &partial); - if (result != 0) { - if (result == -ENOENT) - return US_BULK_TRANSFER_ABORTED; - else - return USB_STOR_TRANSPORT_ERROR; - } - - desired_length = 1; - if (reg == 0x10) - desired_length = 2; - - result = usb_stor_bulk_msg (us, buffer, ipipe, - desired_length, &partial); - if (result != 0) { - if (result == -ENOENT) - return US_BULK_TRANSFER_ABORTED; - else - return USB_STOR_TRANSPORT_ERROR; - } - US_DEBUGP("IDE in partial is %d\n", partial); - - if (desired_length == 1) - *value = buffer[0]; - else - *value = le16_to_cpu (*(__u16 *) buffer); - - US_DEBUGP("IDE in 0x%02x -> 0x%02x\n", reg, *value); - - return USB_STOR_TRANSPORT_GOOD; -} -#endif - static int freecom_readdata (Scsi_Cmnd *srb, struct us_data *us, int ipipe, int opipe, int count) @@ -292,8 +190,8 @@ US_DEBUGP ("Freecom readdata xpot failure: r=%d, p=%d\n", result, partial); - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* has the current command been aborted? */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { US_DEBUGP("freecom_readdata(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -333,8 +231,8 @@ US_DEBUGP ("Freecom writedata xpot failure: r=%d, p=%d\n", result, partial); - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* has the current command been aborted? */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { US_DEBUGP("freecom_writedata(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -396,8 +294,8 @@ US_DEBUGP ("freecom xport failure: r=%d, p=%d\n", result, partial); - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* we canceled this transfer */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { US_DEBUGP("freecom_transport(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -410,8 +308,9 @@ result = usb_stor_bulk_msg (us, fst, ipipe, FCM_PACKET_LENGTH, &partial); US_DEBUGP("foo Status result %d %d\n", result, partial); - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + + /* we canceled this transfer */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { US_DEBUGP("freecom_transport(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -448,8 +347,8 @@ US_DEBUGP ("freecom xport failure: r=%d, p=%d\n", result, partial); - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* we canceled this transfer */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { US_DEBUGP("freecom_transport(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -463,8 +362,8 @@ US_DEBUGP("bar Status result %d %d\n", result, partial); - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { + /* we canceled this transfer */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { US_DEBUGP("freecom_transport(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -524,7 +423,8 @@ result = usb_stor_bulk_msg (us, fst, ipipe, FCM_PACKET_LENGTH, &partial); US_DEBUG(pdump ((void *) fst, partial)); - if (result == -ENOENT) { + + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { US_DEBUGP ("freecom_transport: transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } @@ -552,7 +452,8 @@ US_DEBUGP("FCM: Waiting for status\n"); result = usb_stor_bulk_msg (us, fst, ipipe, FCM_PACKET_LENGTH, &partial); - if (result == -ENOENT) { + + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { US_DEBUGP ("freecom_transport: transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c --- a/drivers/usb/storage/scsiglue.c Sun Jun 2 18:44:57 2002 +++ b/drivers/usb/storage/scsiglue.c Sun Jun 2 18:44:57 2002 @@ -386,9 +386,9 @@ unsigned char usb_stor_sense_notready[18] = { [0] = 0x70, /* current error */ [2] = 0x02, /* not ready */ - [5] = 0x0a, /* additional length */ - [10] = 0x04, /* not ready */ - [11] = 0x03 /* manual intervention */ + [7] = 0x0a, /* additional length */ + [12] = 0x04, /* not ready */ + [13] = 0x03 /* manual intervention */ }; #define USB_STOR_SCSI_SENSE_HDRSZ 4 diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c --- a/drivers/usb/storage/transport.c Sun Jun 2 18:44:57 2002 +++ b/drivers/usb/storage/transport.c Sun Jun 2 18:44:57 2002 @@ -986,9 +986,11 @@ clear_bit(IP_WANTED, &us->bitflags); } - /* if the command was aborted, indicate that */ - if (result == -ENOENT) - return USB_STOR_TRANSPORT_ABORTED; + /* did we abort this command? */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { + US_DEBUGP("usb_stor_control_msg(): transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } /* STALL must be cleared when it is detected */ if (result == -EPIPE) { @@ -996,9 +998,12 @@ result = usb_stor_clear_halt(us, usb_sndctrlpipe(us->pusb_dev, 0)); - /* if the command was aborted, indicate that */ - if (result == -ENOENT) - return USB_STOR_TRANSPORT_ABORTED; + /* did we abort this command? */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { + US_DEBUGP("usb_stor_control_msg(): transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } + return USB_STOR_TRANSPORT_FAILED; } @@ -1098,9 +1103,11 @@ /* check the return code for the command */ US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result); if (result < 0) { - /* if the command was aborted, indicate that */ - if (result == -ENOENT) - return USB_STOR_TRANSPORT_ABORTED; + /* did we abort this command? */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { + US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } /* a stall is a fatal condition from the device */ if (result == -EPIPE) { @@ -1108,9 +1115,11 @@ result = usb_stor_clear_halt(us, usb_sndctrlpipe(us->pusb_dev, 0)); - /* if the command was aborted, indicate that */ - if (result == -ENOENT) - return USB_STOR_TRANSPORT_ABORTED; + /* did we abort this command? */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { + US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } return USB_STOR_TRANSPORT_FAILED; } @@ -1215,18 +1224,22 @@ &partial); US_DEBUGP("Bulk command transfer result=%d\n", result); - /* if the command was aborted, indicate that */ - if (result == -ENOENT) - return USB_STOR_TRANSPORT_ABORTED; + /* did we abort this command? */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { + US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } /* if we stall, we need to clear it before we go on */ if (result == -EPIPE) { US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); result = usb_stor_clear_halt(us, pipe); - /* if the command was aborted, indicate that */ - if (result == -ENOENT) - return USB_STOR_TRANSPORT_ABORTED; + /* did we abort this command? */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { + US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } result = -EPIPE; } else if (result) { /* unknown error -- we've got a problem */ @@ -1259,36 +1272,44 @@ result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN, &partial); - /* if the command was aborted, indicate that */ - if (result == -ENOENT) - return USB_STOR_TRANSPORT_ABORTED; + /* did we abort this command? */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { + US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } /* did the attempt to read the CSW fail? */ if (result == -EPIPE) { US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); result = usb_stor_clear_halt(us, pipe); - /* if the command was aborted, indicate that */ - if (result == -ENOENT) - return USB_STOR_TRANSPORT_ABORTED; + /* did we abort this command? */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { + US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } /* get the status again */ US_DEBUGP("Attempting to get CSW (2nd try)...\n"); result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN, &partial); - /* if the command was aborted, indicate that */ - if (result == -ENOENT) - return USB_STOR_TRANSPORT_ABORTED; + /* did we abort this command? */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { + US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } /* if it fails again, we need a reset and return an error*/ if (result == -EPIPE) { US_DEBUGP("clearing halt for pipe 0x%x\n", pipe); result = usb_stor_clear_halt(us, pipe); - /* if the command was aborted, indicate that */ - if (result == -ENOENT) - return USB_STOR_TRANSPORT_ABORTED; + /* did we abort this command? */ + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { + US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } return USB_STOR_TRANSPORT_ERROR; } } diff -Nru a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c --- a/drivers/video/clps711xfb.c Sun Jun 2 18:44:56 2002 +++ b/drivers/video/clps711xfb.c Sun Jun 2 18:44:56 2002 @@ -158,7 +158,7 @@ clps_writeb(clps_readb(PDDR) & ~EDB_PD1_LCD_DC_DC_EN, PDDR); /* Delay for a little while (half a second). */ - for (i=0; i<65536*4; i++); + udelay(100); /* Power off the LCD panel. */ clps_writeb(clps_readb(PDDR) & ~EDB_PD2_LCDEN, PDDR); @@ -169,24 +169,24 @@ } } else { if (machine_is_edb7211()) { - int i; + int i; - /* Power up the LCD controller. */ - clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN, - SYSCON1); + /* Power up the LCD controller. */ + clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN, + SYSCON1); - /* Power up the LCD panel. */ - clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR); + /* Power up the LCD panel. */ + clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR); - /* Delay for a little while. */ - for (i=0; i<65536*4; i++); + /* Delay for a little while. */ + udelay(100); - /* Power up the LCD DC-DC converter. */ - clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN, - PDDR); + /* Power up the LCD DC-DC converter. */ + clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN, + PDDR); - /* Turn on the LCD backlight. */ - clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR); + /* Turn on the LCD backlight. */ + clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR); } } return 0; diff -Nru a/fs/adfs/adfs.h b/fs/adfs/adfs.h --- a/fs/adfs/adfs.h Sun Jun 2 18:44:58 2002 +++ b/fs/adfs/adfs.h Sun Jun 2 18:44:58 2002 @@ -132,7 +132,7 @@ unsigned int off; off = (object_id & 255) - 1; - block += off << sb->u.adfs_sb.s_log2sharesize; + block += off << ADFS_SB(sb)->s_log2sharesize; } return adfs_map_lookup(sb, object_id >> 8, block); diff -Nru a/fs/adfs/dir.c b/fs/adfs/dir.c --- a/fs/adfs/dir.c Sun Jun 2 18:44:56 2002 +++ b/fs/adfs/dir.c Sun Jun 2 18:44:56 2002 @@ -32,7 +32,7 @@ { struct inode *inode = filp->f_dentry->d_inode; struct super_block *sb = inode->i_sb; - struct adfs_dir_ops *ops = sb->u.adfs_sb.s_dir; + struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir; struct object_info obj; struct adfs_dir dir; int ret = 0; @@ -89,7 +89,7 @@ { int ret = -EINVAL; #ifdef CONFIG_ADFS_FS_RW - struct adfs_dir_ops *ops = sb->u.adfs_sb.s_dir; + struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir; struct adfs_dir dir; printk(KERN_INFO "adfs_dir_update: object %06X in dir %06X\n", @@ -143,7 +143,7 @@ adfs_dir_lookup_byname(struct inode *inode, struct qstr *name, struct object_info *obj) { struct super_block *sb = inode->i_sb; - struct adfs_dir_ops *ops = sb->u.adfs_sb.s_dir; + struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir; struct adfs_dir dir; int ret; @@ -206,7 +206,7 @@ static int adfs_hash(struct dentry *parent, struct qstr *qstr) { - const unsigned int name_len = parent->d_sb->u.adfs_sb.s_namelen; + const unsigned int name_len = ADFS_SB(parent->d_sb)->s_namelen; const unsigned char *name; unsigned long hash; int i; diff -Nru a/fs/adfs/file.c b/fs/adfs/file.c --- a/fs/adfs/file.c Sun Jun 2 18:44:56 2002 +++ b/fs/adfs/file.c Sun Jun 2 18:44:56 2002 @@ -25,7 +25,8 @@ #include #include #include -#include /* for file_fsync() */ +#include /* for file_fsync() */ +#include #include "adfs.h" diff -Nru a/fs/adfs/inode.c b/fs/adfs/inode.c --- a/fs/adfs/inode.c Sun Jun 2 18:44:57 2002 +++ b/fs/adfs/inode.c Sun Jun 2 18:44:57 2002 @@ -102,9 +102,10 @@ { unsigned int filetype, attr = ADFS_I(inode)->attr; umode_t mode, rmask; + struct adfs_sb_info *asb = ADFS_SB(sb); if (attr & ADFS_NDA_DIRECTORY) { - mode = S_IRUGO & sb->u.adfs_sb.s_owner_mask; + mode = S_IRUGO & asb->s_owner_mask; return S_IFDIR | S_IXUGO | mode; } @@ -125,16 +126,16 @@ mode = S_IFREG; if (attr & ADFS_NDA_OWNER_READ) - mode |= rmask & sb->u.adfs_sb.s_owner_mask; + mode |= rmask & asb->s_owner_mask; if (attr & ADFS_NDA_OWNER_WRITE) - mode |= S_IWUGO & sb->u.adfs_sb.s_owner_mask; + mode |= S_IWUGO & asb->s_owner_mask; if (attr & ADFS_NDA_PUBLIC_READ) - mode |= rmask & sb->u.adfs_sb.s_other_mask; + mode |= rmask & asb->s_other_mask; if (attr & ADFS_NDA_PUBLIC_WRITE) - mode |= S_IWUGO & sb->u.adfs_sb.s_other_mask; + mode |= S_IWUGO & asb->s_other_mask; return mode; } @@ -147,6 +148,7 @@ { umode_t mode; int attr; + struct adfs_sb_info *asb = ADFS_SB(sb); /* FIXME: should we be able to alter a link? */ if (S_ISLNK(inode->i_mode)) @@ -157,14 +159,14 @@ else attr = 0; - mode = inode->i_mode & sb->u.adfs_sb.s_owner_mask; + mode = inode->i_mode & asb->s_owner_mask; if (mode & S_IRUGO) attr |= ADFS_NDA_OWNER_READ; if (mode & S_IWUGO) attr |= ADFS_NDA_OWNER_WRITE; - mode = inode->i_mode & sb->u.adfs_sb.s_other_mask; - mode &= ~sb->u.adfs_sb.s_owner_mask; + mode = inode->i_mode & asb->s_other_mask; + mode &= ~asb->s_owner_mask; if (mode & S_IRUGO) attr |= ADFS_NDA_PUBLIC_READ; if (mode & S_IWUGO) @@ -247,8 +249,8 @@ if (!inode) goto out; - inode->i_uid = sb->u.adfs_sb.s_uid; - inode->i_gid = sb->u.adfs_sb.s_gid; + inode->i_uid = ADFS_SB(sb)->s_uid; + inode->i_gid = ADFS_SB(sb)->s_gid; inode->i_ino = obj->file_id; inode->i_size = obj->size; inode->i_nlink = 2; @@ -310,8 +312,8 @@ * we can't change the UID or GID of any file - * we have a global UID/GID in the superblock */ - if ((ia_valid & ATTR_UID && attr->ia_uid != sb->u.adfs_sb.s_uid) || - (ia_valid & ATTR_GID && attr->ia_gid != sb->u.adfs_sb.s_gid)) + if ((ia_valid & ATTR_UID && attr->ia_uid != ADFS_SB(sb)->s_uid) || + (ia_valid & ATTR_GID && attr->ia_gid != ADFS_SB(sb)->s_gid)) error = -EPERM; if (error) diff -Nru a/fs/adfs/map.c b/fs/adfs/map.c --- a/fs/adfs/map.c Sun Jun 2 18:44:57 2002 +++ b/fs/adfs/map.c Sun Jun 2 18:44:57 2002 @@ -238,7 +238,7 @@ unsigned int adfs_map_free(struct super_block *sb) { - struct adfs_sb_info *asb = &sb->u.adfs_sb; + struct adfs_sb_info *asb = ADFS_SB(sb); struct adfs_discmap *dm; unsigned int total = 0; unsigned int zone; diff -Nru a/fs/adfs/super.c b/fs/adfs/super.c --- a/fs/adfs/super.c Sun Jun 2 18:44:56 2002 +++ b/fs/adfs/super.c Sun Jun 2 18:44:56 2002 @@ -105,7 +105,7 @@ unsigned char crosscheck = 0, zonecheck = 1; int i; - for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) { + for (i = 0; i < ADFS_SB(sb)->s_map_size; i++) { unsigned char *map; map = dm[i].dm_bh->b_data; @@ -124,15 +124,19 @@ static void adfs_put_super(struct super_block *sb) { int i; + struct adfs_sb_info *asb = ADFS_SB(sb); - for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) - brelse(sb->u.adfs_sb.s_map[i].dm_bh); - kfree(sb->u.adfs_sb.s_map); + for (i = 0; i < asb->s_map_size; i++) + brelse(asb->s_map[i].dm_bh); + kfree(asb->s_map); + kfree(asb); + sb->u.generic_sbp = NULL; } static int parse_options(struct super_block *sb, char *options) { char *value, *opt; + struct adfs_sb_info *asb = ADFS_SB(sb); if (!options) return 0; @@ -147,28 +151,28 @@ if (!strcmp(opt, "uid")) { /* owner of all files */ if (!value || !*value) return -EINVAL; - sb->u.adfs_sb.s_uid = simple_strtoul(value, &value, 0); + asb->s_uid = simple_strtoul(value, &value, 0); if (*value) return -EINVAL; } else if (!strcmp(opt, "gid")) { /* group owner of all files */ if (!value || !*value) return -EINVAL; - sb->u.adfs_sb.s_gid = simple_strtoul(value, &value, 0); + asb->s_gid = simple_strtoul(value, &value, 0); if (*value) return -EINVAL; } else if (!strcmp(opt, "ownmask")) { /* owner permission mask */ if (!value || !*value) return -EINVAL; - sb->u.adfs_sb.s_owner_mask = simple_strtoul(value, &value, 8); + asb->s_owner_mask = simple_strtoul(value, &value, 8); if (*value) return -EINVAL; } else if (!strcmp(opt, "othmask")) { /* others permission mask */ if (!value || !*value) return -EINVAL; - sb->u.adfs_sb.s_other_mask = simple_strtoul(value, &value, 8); + asb->s_other_mask = simple_strtoul(value, &value, 8); if (*value) return -EINVAL; } else { /* eh? say again. */ @@ -186,7 +190,7 @@ static int adfs_statfs(struct super_block *sb, struct statfs *buf) { - struct adfs_sb_info *asb = &sb->u.adfs_sb; + struct adfs_sb_info *asb = ADFS_SB(sb); buf->f_type = ADFS_SUPER_MAGIC; buf->f_namelen = asb->s_namelen; @@ -256,14 +260,15 @@ struct adfs_discmap *dm; unsigned int map_addr, zone_size, nzones; int i, zone; + struct adfs_sb_info *asb = ADFS_SB(sb); - nzones = sb->u.adfs_sb.s_map_size; + nzones = asb->s_map_size; zone_size = (8 << dr->log2secsize) - le16_to_cpu(dr->zone_spare); map_addr = (nzones >> 1) * zone_size - ((nzones > 1) ? ADFS_DR_SIZE_BITS : 0); - map_addr = signed_asl(map_addr, sb->u.adfs_sb.s_map2blk); + map_addr = signed_asl(map_addr, asb->s_map2blk); - sb->u.adfs_sb.s_ids_per_zone = zone_size / (sb->u.adfs_sb.s_idlen + 1); + asb->s_ids_per_zone = zone_size / (asb->s_idlen + 1); dm = kmalloc(nzones * sizeof(*dm), GFP_KERNEL); if (dm == NULL) { @@ -320,12 +325,19 @@ struct buffer_head *bh; struct object_info root_obj; unsigned char *b_data; + struct adfs_sb_info *asb; + + asb = kmalloc(sizeof(*asb), GFP_KERNEL); + if (!asb) + return -ENOMEM; + sb->u.generic_sbp = asb; + memset(asb, 0, sizeof(*asb)); /* set default options */ - sb->u.adfs_sb.s_uid = 0; - sb->u.adfs_sb.s_gid = 0; - sb->u.adfs_sb.s_owner_mask = S_IRWXU; - sb->u.adfs_sb.s_other_mask = S_IRWXG | S_IRWXO; + asb->s_uid = 0; + asb->s_gid = 0; + asb->s_owner_mask = S_IRWXU; + asb->s_other_mask = S_IRWXG | S_IRWXO; if (parse_options(sb, data)) goto error; @@ -382,16 +394,16 @@ * blocksize on this device should now be set to the ADFS log2secsize */ - sb->s_magic = ADFS_SUPER_MAGIC; - sb->u.adfs_sb.s_idlen = dr->idlen; - sb->u.adfs_sb.s_map_size = dr->nzones | (dr->nzones_high << 8); - sb->u.adfs_sb.s_map2blk = dr->log2bpmb - dr->log2secsize; - sb->u.adfs_sb.s_size = adfs_discsize(dr, sb->s_blocksize_bits); - sb->u.adfs_sb.s_version = dr->format_version; - sb->u.adfs_sb.s_log2sharesize = dr->log2sharesize; + sb->s_magic = ADFS_SUPER_MAGIC; + asb->s_idlen = dr->idlen; + asb->s_map_size = dr->nzones | (dr->nzones_high << 8); + asb->s_map2blk = dr->log2bpmb - dr->log2secsize; + asb->s_size = adfs_discsize(dr, sb->s_blocksize_bits); + asb->s_version = dr->format_version; + asb->s_log2sharesize = dr->log2sharesize; - sb->u.adfs_sb.s_map = adfs_read_map(sb, dr); - if (!sb->u.adfs_sb.s_map) + asb->s_map = adfs_read_map(sb, dr); + if (!asb->s_map) goto error_free_bh; brelse(bh); @@ -401,7 +413,7 @@ */ sb->s_op = &adfs_sops; - dr = (struct adfs_discrecord *)(sb->u.adfs_sb.s_map[0].dm_bh->b_data + 4); + dr = (struct adfs_discrecord *)(asb->s_map[0].dm_bh->b_data + 4); root_obj.parent_id = root_obj.file_id = le32_to_cpu(dr->root); root_obj.name_len = 0; @@ -415,22 +427,22 @@ * If this is a F+ disk with variable length directories, * get the root_size from the disc record. */ - if (sb->u.adfs_sb.s_version) { + if (asb->s_version) { root_obj.size = dr->root_size; - sb->u.adfs_sb.s_dir = &adfs_fplus_dir_ops; - sb->u.adfs_sb.s_namelen = ADFS_FPLUS_NAME_LEN; + asb->s_dir = &adfs_fplus_dir_ops; + asb->s_namelen = ADFS_FPLUS_NAME_LEN; } else { - sb->u.adfs_sb.s_dir = &adfs_f_dir_ops; - sb->u.adfs_sb.s_namelen = ADFS_F_NAME_LEN; + asb->s_dir = &adfs_f_dir_ops; + asb->s_namelen = ADFS_F_NAME_LEN; } sb->s_root = d_alloc_root(adfs_iget(sb, &root_obj)); if (!sb->s_root) { int i; - for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) - brelse(sb->u.adfs_sb.s_map[i].dm_bh); - kfree(sb->u.adfs_sb.s_map); + for (i = 0; i < asb->s_map_size; i++) + brelse(asb->s_map[i].dm_bh); + kfree(asb->s_map); adfs_error(sb, "get root inode failed\n"); goto error; } else @@ -440,6 +452,8 @@ error_free_bh: brelse(bh); error: + sb->u.generic_sbp = NULL; + kfree(asb); return -EINVAL; } diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c --- a/fs/binfmt_elf.c Sun Jun 2 18:44:57 2002 +++ b/fs/binfmt_elf.c Sun Jun 2 18:44:57 2002 @@ -607,7 +607,12 @@ /* Do this so that we can load the interpreter, if need be. We will change some of these later */ current->mm->rss = 0; - setup_arg_pages(bprm); /* XXX: check error */ + retval = setup_arg_pages(bprm); + if (retval < 0) { + send_sig(SIGKILL, current, 0); + return retval; + } + current->mm->start_stack = bprm->p; /* Now we do a little grungy work by mmaping the ELF image into @@ -1279,3 +1284,4 @@ module_init(init_elf_binfmt) module_exit(exit_elf_binfmt) +MODULE_LICENSE("GPL"); diff -Nru a/fs/binfmt_em86.c b/fs/binfmt_em86.c --- a/fs/binfmt_em86.c Sun Jun 2 18:44:58 2002 +++ b/fs/binfmt_em86.c Sun Jun 2 18:44:58 2002 @@ -112,3 +112,4 @@ module_init(init_em86_binfmt) module_exit(exit_em86_binfmt) +MODULE_LICENSE("GPL"); diff -Nru a/fs/binfmt_script.c b/fs/binfmt_script.c --- a/fs/binfmt_script.c Sun Jun 2 18:44:56 2002 +++ b/fs/binfmt_script.c Sun Jun 2 18:44:56 2002 @@ -111,3 +111,4 @@ module_init(init_script_binfmt) module_exit(exit_script_binfmt) +MODULE_LICENSE("GPL"); diff -Nru a/fs/buffer.c b/fs/buffer.c --- a/fs/buffer.c Sun Jun 2 18:44:56 2002 +++ b/fs/buffer.c Sun Jun 2 18:44:56 2002 @@ -1341,22 +1341,21 @@ } /** - * block_flushpage - invalidate part of all of a buffer-backed page + * block_invalidatepage - invalidate part of all of a buffer-backed page * * @page: the page which is affected * @offset: the index of the truncation point * - * block_flushpage() should be called block_invalidatepage(). It is - * called when all or part of the page has become invalidatedby a truncate - * operation. + * block_invalidatepage() is called when all or part of the page has become + * invalidatedby a truncate operation. * - * block_flushpage() does not have to release all buffers, but it must + * block_invalidatepage() does not have to release all buffers, but it must * ensure that no dirty buffer is left outside @offset and that no I/O * is underway against any of the blocks which are outside the truncation * point. Because the caller is about to free (and possibly reuse) those * blocks on-disk. */ -int block_flushpage(struct page *page, unsigned long offset) +int block_invalidatepage(struct page *page, unsigned long offset) { struct buffer_head *head, *bh, *next; unsigned int curr_off = 0; @@ -1393,7 +1392,7 @@ return 1; } -EXPORT_SYMBOL(block_flushpage); +EXPORT_SYMBOL(block_invalidatepage); /* * We attach and possibly dirty the buffers atomically wrt @@ -2276,10 +2275,11 @@ * some of the bmap kludges and interface ugliness here. * * NOTE: unlike file pages, swap pages are locked while under writeout. - * This is to avoid a deadlock which occurs when free_swap_and_cache() - * calls block_flushpage() under spinlock and hits a locked buffer, and - * schedules under spinlock. Another approach would be to teach - * find_trylock_page() to also trylock the page's writeback flags. + * This is to throttle processes which reuse their swapcache pages while + * they are under writeout, and to ensure that there is no I/O going on + * when the page has been successfully locked. Functions such as + * free_swap_and_cache() need to guarantee that there is no I/O in progress + * because they will be freeing up swap blocks, which may then be reused. * * Swap pages are also marked PageWriteback when they are being written * so that memory allocators will throttle on them. @@ -2325,46 +2325,6 @@ bh = next; } while (bh != head); return 0; -} - -int block_symlink(struct inode *inode, const char *symname, int len) -{ - struct address_space *mapping = inode->i_mapping; - struct page *page = grab_cache_page(mapping, 0); - int err = -ENOMEM; - char *kaddr; - - if (!page) - goto fail; - err = mapping->a_ops->prepare_write(NULL, page, 0, len-1); - if (err) - goto fail_map; - kaddr = page_address(page); - memcpy(kaddr, symname, len-1); - mapping->a_ops->commit_write(NULL, page, 0, len-1); - /* - * Notice that we are _not_ going to block here - end of page is - * unmapped, so this will only try to map the rest of page, see - * that it is unmapped (typically even will not look into inode - - * ->i_size will be enough for everything) and zero it out. - * OTOH it's obviously correct and should make the page up-to-date. - */ - if (!PageUptodate(page)) { - err = mapping->a_ops->readpage(NULL, page); - wait_on_page_locked(page); - } else { - unlock_page(page); - } - page_cache_release(page); - if (err < 0) - goto fail; - mark_inode_dirty(inode); - return 0; -fail_map: - unlock_page(page); - page_cache_release(page); -fail: - return err; } /* diff -Nru a/fs/driverfs/inode.c b/fs/driverfs/inode.c --- a/fs/driverfs/inode.c Sun Jun 2 18:44:56 2002 +++ b/fs/driverfs/inode.c Sun Jun 2 18:44:56 2002 @@ -80,7 +80,6 @@ flush_dcache_page(page); SetPageUptodate(page); } - SetPageDirty(page); return 0; } @@ -89,6 +88,7 @@ struct inode *inode = page->mapping->host; loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; + set_page_dirty(page); kunmap(page); if (pos > inode->i_size) inode->i_size = pos; @@ -171,7 +171,7 @@ inode = driverfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0); if (inode) { int l = strlen(symname)+1; - error = block_symlink(inode, symname, l); + error = page_symlink(inode, symname, l); if (!error) { d_instantiate(dentry, inode); dget(dentry); @@ -707,6 +707,7 @@ if (!strcmp(entry->name,name)) { list_del_init(node); vfs_unlink(entry->dentry->d_parent->d_inode,entry->dentry); + dput(entry->dentry); put_mount(); break; } @@ -731,7 +732,6 @@ if (!dentry) goto done; - dget(dentry); down(&dentry->d_parent->d_inode->i_sem); down(&dentry->d_inode->i_sem); @@ -742,6 +742,7 @@ list_del_init(node); vfs_unlink(dentry->d_inode,entry->dentry); + dput(entry->dentry); put_mount(); node = dir->files.next; } diff -Nru a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c --- a/fs/exportfs/expfs.c Sun Jun 2 18:44:57 2002 +++ b/fs/exportfs/expfs.c Sun Jun 2 18:44:57 2002 @@ -524,3 +524,5 @@ EXPORT_SYMBOL(export_op_default); EXPORT_SYMBOL(find_exported_dentry); + +MODULE_LICENSE("GPL"); diff -Nru a/fs/ext2/namei.c b/fs/ext2/namei.c --- a/fs/ext2/namei.c Sun Jun 2 18:44:58 2002 +++ b/fs/ext2/namei.c Sun Jun 2 18:44:58 2002 @@ -31,7 +31,6 @@ #include "ext2.h" #include -#include /* for block_symlink() */ /* * Couple of helper functions - make the code slightly cleaner. @@ -165,7 +164,7 @@ /* slow symlink */ inode->i_op = &page_symlink_inode_operations; inode->i_mapping->a_ops = &ext2_aops; - err = block_symlink(inode, symname, l); + err = page_symlink(inode, symname, l); if (err) goto out_fail; } else { diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c --- a/fs/ext3/inode.c Sun Jun 2 18:44:58 2002 +++ b/fs/ext3/inode.c Sun Jun 2 18:44:58 2002 @@ -306,6 +306,8 @@ * @inode: inode in question (we are only interested in its superblock) * @i_block: block number to be parsed * @offsets: array to store the offsets in + * @boundary: set this non-zero if the referred-to block is likely to be + * followed (on disk) by an indirect block. * * To store the locations of file's data ext3 uses a data structure common * for UNIX filesystems - tree of pointers anchored in the inode, with @@ -330,7 +332,8 @@ * get there at all. */ -static int ext3_block_to_path(struct inode *inode, long i_block, int offsets[4]) +static int ext3_block_to_path(struct inode *inode, + long i_block, int offsets[4], int *boundary) { int ptrs = EXT3_ADDR_PER_BLOCK(inode->i_sb); int ptrs_bits = EXT3_ADDR_PER_BLOCK_BITS(inode->i_sb); @@ -338,26 +341,33 @@ indirect_blocks = ptrs, double_blocks = (1 << (ptrs_bits * 2)); int n = 0; + int final = 0; if (i_block < 0) { ext3_warning (inode->i_sb, "ext3_block_to_path", "block < 0"); } else if (i_block < direct_blocks) { offsets[n++] = i_block; + final = direct_blocks; } else if ( (i_block -= direct_blocks) < indirect_blocks) { offsets[n++] = EXT3_IND_BLOCK; offsets[n++] = i_block; + final = ptrs; } else if ((i_block -= indirect_blocks) < double_blocks) { offsets[n++] = EXT3_DIND_BLOCK; offsets[n++] = i_block >> ptrs_bits; offsets[n++] = i_block & (ptrs - 1); + final = ptrs; } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) { offsets[n++] = EXT3_TIND_BLOCK; offsets[n++] = i_block >> (ptrs_bits * 2); offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1); offsets[n++] = i_block & (ptrs - 1); + final = ptrs; } else { ext3_warning (inode->i_sb, "ext3_block_to_path", "block > big"); } + if (boundary) + *boundary = (i_block & (ptrs - 1)) == (final - 1); return n; } @@ -734,7 +744,8 @@ Indirect *partial; unsigned long goal; int left; - int depth = ext3_block_to_path(inode, iblock, offsets); + int boundary = 0; + int depth = ext3_block_to_path(inode, iblock, offsets, &boundary); struct ext3_inode_info *ei = EXT3_I(inode); loff_t new_size; @@ -752,6 +763,8 @@ clear_buffer_new(bh_result); got_it: map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key)); + if (boundary) + set_buffer_boundary(bh_result); /* Clean up and exit */ partial = chain+depth-1; /* the whole chain */ goto cleanup; @@ -1079,7 +1092,7 @@ /* * We need to pick up the new inode size which generic_commit_write gave us - * `file' can be NULL - eg, when called from block_symlink(). + * `file' can be NULL - eg, when called from page_symlink(). * * ext3 never places buffers on inode->i_mapping->private_list. metadata * buffers are managed internally. @@ -1351,10 +1364,10 @@ return mpage_readpages(mapping, pages, nr_pages, ext3_get_block); } -static int ext3_flushpage(struct page *page, unsigned long offset) +static int ext3_invalidatepage(struct page *page, unsigned long offset) { journal_t *journal = EXT3_JOURNAL(page->mapping->host); - return journal_flushpage(journal, page, offset); + return journal_invalidatepage(journal, page, offset); } static int ext3_releasepage(struct page *page, int wait) @@ -1372,7 +1385,35 @@ prepare_write: ext3_prepare_write, /* BKL not held. We take it */ commit_write: ext3_commit_write, /* BKL not held. We take it */ bmap: ext3_bmap, /* BKL held */ - flushpage: ext3_flushpage, /* BKL not held. Don't need */ + invalidatepage: ext3_invalidatepage, /* BKL not held. Don't need */ + releasepage: ext3_releasepage, /* BKL not held. Don't need */ +}; + +/* For writeback mode, we can use mpage_writepages() */ + +static int +ext3_writepages(struct address_space *mapping, int *nr_to_write) +{ + int ret; + int err; + + ret = write_mapping_buffers(mapping); + err = mpage_writepages(mapping, nr_to_write, ext3_get_block); + if (!ret) + ret = err; + return ret; +} + +struct address_space_operations ext3_writeback_aops = { + readpage: ext3_readpage, /* BKL not held. Don't need */ + readpages: ext3_readpages, /* BKL not held. Don't need */ + writepage: ext3_writepage, /* BKL not held. We take it */ + writepages: ext3_writepages, /* BKL not held. Don't need */ + sync_page: block_sync_page, + prepare_write: ext3_prepare_write, /* BKL not held. We take it */ + commit_write: ext3_commit_write, /* BKL not held. We take it */ + bmap: ext3_bmap, /* BKL held */ + invalidatepage: ext3_invalidatepage, /* BKL not held. Don't need */ releasepage: ext3_releasepage, /* BKL not held. Don't need */ }; @@ -1875,7 +1916,7 @@ ext3_block_truncate_page(handle, inode->i_mapping, inode->i_size); - n = ext3_block_to_path(inode, last_block, offsets); + n = ext3_block_to_path(inode, last_block, offsets, NULL); if (n == 0) goto out_stop; /* error */ @@ -2146,7 +2187,10 @@ else if (S_ISREG(inode->i_mode)) { inode->i_op = &ext3_file_inode_operations; inode->i_fop = &ext3_file_operations; - inode->i_mapping->a_ops = &ext3_aops; + if (ext3_should_writeback_data(inode)) + inode->i_mapping->a_ops = &ext3_writeback_aops; + else + inode->i_mapping->a_ops = &ext3_aops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &ext3_dir_inode_operations; inode->i_fop = &ext3_dir_operations; @@ -2155,7 +2199,10 @@ inode->i_op = &ext3_fast_symlink_inode_operations; else { inode->i_op = &page_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; + if (ext3_should_writeback_data(inode)) + inode->i_mapping->a_ops = &ext3_writeback_aops; + else + inode->i_mapping->a_ops = &ext3_aops; } } else init_special_inode(inode, inode->i_mode, diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c --- a/fs/ext3/namei.c Sun Jun 2 18:44:58 2002 +++ b/fs/ext3/namei.c Sun Jun 2 18:44:58 2002 @@ -510,7 +510,10 @@ if (!IS_ERR(inode)) { inode->i_op = &ext3_file_inode_operations; inode->i_fop = &ext3_file_operations; - inode->i_mapping->a_ops = &ext3_aops; + if (ext3_should_writeback_data(inode)) + inode->i_mapping->a_ops = &ext3_writeback_aops; + else + inode->i_mapping->a_ops = &ext3_aops; ext3_mark_inode_dirty(handle, inode); err = ext3_add_nondir(handle, dentry, inode); } @@ -985,13 +988,16 @@ if (l > sizeof (EXT3_I(inode)->i_data)) { inode->i_op = &page_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; + if (ext3_should_writeback_data(inode)) + inode->i_mapping->a_ops = &ext3_writeback_aops; + else + inode->i_mapping->a_ops = &ext3_aops; /* - * block_symlink() calls back into ext3_prepare/commit_write. + * page_symlink() calls into ext3_prepare/commit_write. * We have a transaction open. All is sweetness. It also sets * i_size in generic_commit_write(). */ - err = block_symlink(inode, symname, l); + err = page_symlink(inode, symname, l); if (err) goto out_no_entry; } else { diff -Nru a/fs/fs-writeback.c b/fs/fs-writeback.c --- a/fs/fs-writeback.c Sun Jun 2 18:44:57 2002 +++ b/fs/fs-writeback.c Sun Jun 2 18:44:57 2002 @@ -176,8 +176,7 @@ } } } - if (waitqueue_active(&inode->i_wait)) - wake_up(&inode->i_wait); + wake_up_inode(inode); } /* @@ -246,17 +245,19 @@ if ((sync_mode == WB_SYNC_LAST) && (head->prev == head)) really_sync = 1; + BUG_ON(inode->i_state & I_FREEING); + __iget(inode); __writeback_single_inode(inode, really_sync, nr_to_write); - if (sync_mode == WB_SYNC_HOLD) { mapping->dirtied_when = jiffies; list_del(&inode->i_list); list_add(&inode->i_list, &inode->i_sb->s_dirty); } - if (current_is_pdflush()) writeback_release(bdi); - + spin_unlock(&inode_lock); + iput(inode); + spin_lock(&inode_lock); if (nr_to_write && *nr_to_write <= 0) break; } diff -Nru a/fs/hpfs/super.c b/fs/hpfs/super.c --- a/fs/hpfs/super.c Sun Jun 2 18:44:58 2002 +++ b/fs/hpfs/super.c Sun Jun 2 18:44:58 2002 @@ -649,3 +649,4 @@ module_init(init_hpfs_fs) module_exit(exit_hpfs_fs) +MODULE_LICENSE("GPL"); diff -Nru a/fs/inode.c b/fs/inode.c --- a/fs/inode.c Sun Jun 2 18:44:57 2002 +++ b/fs/inode.c Sun Jun 2 18:44:57 2002 @@ -14,6 +14,9 @@ #include #include #include +#include +#include + /* * This is needed for the following functions: * - inode_has_buffers @@ -149,7 +152,6 @@ void inode_init_once(struct inode *inode) { memset(inode, 0, sizeof(*inode)); - init_waitqueue_head(&inode->i_wait); INIT_LIST_HEAD(&inode->i_hash); INIT_LIST_HEAD(&inode->i_data.clean_pages); INIT_LIST_HEAD(&inode->i_data.dirty_pages); @@ -176,21 +178,6 @@ inode_init_once(inode); } -void __wait_on_inode(struct inode * inode) -{ - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue(&inode->i_wait, &wait); -repeat: - set_current_state(TASK_UNINTERRUPTIBLE); - if (inode->i_state & I_LOCK) { - schedule(); - goto repeat; - } - remove_wait_queue(&inode->i_wait, &wait); - current->state = TASK_RUNNING; -} - /* * inode_lock must be held */ @@ -538,7 +525,7 @@ * that haven't tested I_LOCK). */ inode->i_state &= ~(I_LOCK|I_NEW); - wake_up(&inode->i_wait); + wake_up_inode(inode); } @@ -899,59 +886,6 @@ return res; } -/* - * Initialize the hash tables. - */ -void __init inode_init(unsigned long mempages) -{ - struct list_head *head; - unsigned long order; - unsigned int nr_hash; - int i; - - mempages >>= (14 - PAGE_SHIFT); - mempages *= sizeof(struct list_head); - for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++) - ; - - do { - unsigned long tmp; - - nr_hash = (1UL << order) * PAGE_SIZE / - sizeof(struct list_head); - i_hash_mask = (nr_hash - 1); - - tmp = nr_hash; - i_hash_shift = 0; - while ((tmp >>= 1UL) != 0UL) - i_hash_shift++; - - inode_hashtable = (struct list_head *) - __get_free_pages(GFP_ATOMIC, order); - } while (inode_hashtable == NULL && --order >= 0); - - printk("Inode-cache hash table entries: %d (order: %ld, %ld bytes)\n", - nr_hash, order, (PAGE_SIZE << order)); - - if (!inode_hashtable) - panic("Failed to allocate inode hash table\n"); - - head = inode_hashtable; - i = nr_hash; - do { - INIT_LIST_HEAD(head); - head++; - i--; - } while (i); - - /* inode slab cache */ - inode_cachep = kmem_cache_create("inode_cache", sizeof(struct inode), - 0, SLAB_HWCACHE_ALIGN, init_once, - NULL); - if (!inode_cachep) - panic("cannot create inode slab cache"); -} - static inline void do_atime_update(struct inode *inode) { unsigned long time = CURRENT_TIME; @@ -1044,3 +978,104 @@ } #endif + +/* + * Hashed waitqueues for wait_on_inode(). The table is pretty small - the + * kernel doesn't lock many inodes at the same time. + */ +#define I_WAIT_TABLE_ORDER 3 +static struct i_wait_queue_head { + wait_queue_head_t wqh; +} ____cacheline_aligned_in_smp i_wait_queue_heads[1<i_state & I_LOCK) { + schedule(); + goto repeat; + } + remove_wait_queue(wq, &wait); + current->state = TASK_RUNNING; +} + +void wake_up_inode(struct inode *inode) +{ + wait_queue_head_t *wq = i_waitq_head(inode); + + /* + * Prevent speculative execution through spin_unlock(&inode_lock); + */ + smp_mb(); + if (waitqueue_active(wq)) + wake_up_all(wq); +} + +/* + * Initialize the waitqueues and inode hash table. + */ +void __init inode_init(unsigned long mempages) +{ + struct list_head *head; + unsigned long order; + unsigned int nr_hash; + int i; + + for (i = 0; i < ARRAY_SIZE(i_wait_queue_heads); i++) + init_waitqueue_head(&i_wait_queue_heads[i].wqh); + + mempages >>= (14 - PAGE_SHIFT); + mempages *= sizeof(struct list_head); + for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++) + ; + + do { + unsigned long tmp; + + nr_hash = (1UL << order) * PAGE_SIZE / + sizeof(struct list_head); + i_hash_mask = (nr_hash - 1); + + tmp = nr_hash; + i_hash_shift = 0; + while ((tmp >>= 1UL) != 0UL) + i_hash_shift++; + + inode_hashtable = (struct list_head *) + __get_free_pages(GFP_ATOMIC, order); + } while (inode_hashtable == NULL && --order >= 0); + + printk("Inode-cache hash table entries: %d (order: %ld, %ld bytes)\n", + nr_hash, order, (PAGE_SIZE << order)); + + if (!inode_hashtable) + panic("Failed to allocate inode hash table\n"); + + head = inode_hashtable; + i = nr_hash; + do { + INIT_LIST_HEAD(head); + head++; + i--; + } while (i); + + /* inode slab cache */ + inode_cachep = kmem_cache_create("inode_cache", sizeof(struct inode), + 0, SLAB_HWCACHE_ALIGN, init_once, + NULL); + if (!inode_cachep) + panic("cannot create inode slab cache"); +} diff -Nru a/fs/jbd/journal.c b/fs/jbd/journal.c --- a/fs/jbd/journal.c Sun Jun 2 18:44:56 2002 +++ b/fs/jbd/journal.c Sun Jun 2 18:44:56 2002 @@ -78,7 +78,7 @@ EXPORT_SYMBOL(log_start_commit); EXPORT_SYMBOL(journal_wipe); EXPORT_SYMBOL(journal_blocks_per_page); -EXPORT_SYMBOL(journal_flushpage); +EXPORT_SYMBOL(journal_invalidatepage); EXPORT_SYMBOL(journal_try_to_free_buffers); EXPORT_SYMBOL(journal_bmap); EXPORT_SYMBOL(journal_force_commit); diff -Nru a/fs/jbd/transaction.c b/fs/jbd/transaction.c --- a/fs/jbd/transaction.c Sun Jun 2 18:44:57 2002 +++ b/fs/jbd/transaction.c Sun Jun 2 18:44:57 2002 @@ -1749,13 +1749,13 @@ } /* - * journal_flushpage + * journal_invalidatepage * * This code is tricky. It has a number of cases to deal with. * * There are two invariants which this code relies on: * - * i_size must be updated on disk before we start calling flushpage on the + * i_size must be updated on disk before we start calling invalidatepage on the * data. * * This is done in ext3 by defining an ext3_setattr method which @@ -1891,7 +1891,7 @@ /* * Return non-zero if the page's buffers were successfully reaped */ -int journal_flushpage(journal_t *journal, +int journal_invalidatepage(journal_t *journal, struct page *page, unsigned long offset) { diff -Nru a/fs/jfs/inode.c b/fs/jfs/inode.c --- a/fs/jfs/inode.c Sun Jun 2 18:44:55 2002 +++ b/fs/jfs/inode.c Sun Jun 2 18:44:55 2002 @@ -34,17 +34,18 @@ struct address_space_operations jfs_aops; extern int freeZeroLink(struct inode *); -void jfs_put_inode(struct inode *inode) +struct inode *jfs_iget(struct super_block *sb, ino_t ino) { - jFYI(1, ("In jfs_put_inode, inode = 0x%p\n", inode)); -} + struct inode *inode = iget_locked(sb, ino); -void jfs_read_inode(struct inode *inode) -{ - jFYI(1, ("In jfs_read_inode, inode = 0x%p\n", inode)); + if (!inode || !(inode->i_state & I_NEW)) + return inode; - if (diRead(inode)) - goto bad_inode; + if (diRead(inode)) { + make_bad_inode(inode); + unlock_new_inode(inode); + return NULL; + } if (S_ISREG(inode->i_mode)) { inode->i_op = &jfs_file_inode_operations; @@ -65,11 +66,8 @@ init_special_inode(inode, inode->i_mode, kdev_t_to_nr(inode->i_rdev)); } - - return; - - bad_inode: - make_bad_inode(inode); + unlock_new_inode(inode); + return inode; } /* This define is from fs/open.c */ diff -Nru a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c --- a/fs/jfs/jfs_dmap.c Sun Jun 2 18:44:57 2002 +++ b/fs/jfs/jfs_dmap.c Sun Jun 2 18:44:57 2002 @@ -782,8 +782,7 @@ nblocks); } - IWRITE_UNLOCK(ipbmap); - return (rc); + goto write_unlock; } /* we would like to allocate close to the hint. adjust the @@ -829,12 +828,12 @@ /* get the buffer for the dmap containing the hint. */ + rc = EIO; lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage); mp = read_metapage(ipbmap, lblkno, PSIZE, 0); - if (mp == NULL) { - IREAD_UNLOCK(ipbmap); - return (EIO); - } + if (mp == NULL) + goto read_unlock; + dp = (dmap_t *) mp->data; /* first, try to satisfy the allocation request with the @@ -847,14 +846,11 @@ *results = blkno; DBALLOC(bmp->db_DBmap, bmp->db_mapsize, *results, nblocks); - write_metapage(mp); - } else { - assert(rc == EIO); - release_metapage(mp); + mark_metapage_dirty(mp); } - IREAD_UNLOCK(ipbmap); - return (rc); + release_metapage(mp); + goto read_unlock; } /* next, try to satisfy the allocation request with blocks @@ -869,10 +865,9 @@ *results, nblocks); mark_metapage_dirty(mp); } - release_metapage(mp); - IREAD_UNLOCK(ipbmap); - return (rc); + release_metapage(mp); + goto read_unlock; } /* try to satisfy the allocation request with blocks within @@ -886,10 +881,9 @@ *results, nblocks); mark_metapage_dirty(mp); } - release_metapage(mp); - IREAD_UNLOCK(ipbmap); - return (rc); + release_metapage(mp); + goto read_unlock; } release_metapage(mp); @@ -910,7 +904,13 @@ DBALLOC(bmp->db_DBmap, bmp->db_mapsize, *results, nblocks); } + write_unlock: IWRITE_UNLOCK(ipbmap); + + return (rc); + + read_unlock: + IREAD_UNLOCK(ipbmap); return (rc); } diff -Nru a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h --- a/fs/jfs/jfs_incore.h Sun Jun 2 18:44:56 2002 +++ b/fs/jfs/jfs_incore.h Sun Jun 2 18:44:56 2002 @@ -143,8 +143,17 @@ { return list_entry(inode, struct jfs_inode_info, vfs_inode); } -#define JFS_SBI(sb) ((struct jfs_sb_info *)(sb)->u.generic_sbp) -#define isReadOnly(ip) ((JFS_SBI((ip)->i_sb)->log) ? 0 : 1) +static inline struct jfs_sb_info *JFS_SBI(struct super_block *sb) +{ + return sb->u.generic_sbp; +} + +static inline int isReadOnly(struct inode *inode) +{ + if (JFS_SBI(inode->i_sb)->log) + return 0; + return 1; +} #endif /* _H_JFS_INCORE */ diff -Nru a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c --- a/fs/jfs/jfs_logmgr.c Sun Jun 2 18:44:57 2002 +++ b/fs/jfs/jfs_logmgr.c Sun Jun 2 18:44:57 2002 @@ -1068,6 +1068,8 @@ return ENOMEM; memset(log, 0, sizeof(log_t)); + log->sb = sb; /* This should be a list */ + if (!(JFS_SBI(sb)->mntflag & JFS_INLINELOG)) goto externalLog; @@ -1077,7 +1079,6 @@ * file system to log have 1-to-1 relationship; */ - log->sb = sb; /* This should be a list */ log->bdev = sb->s_bdev; log->flag = JFS_INLINELOG; log->base = addressPXD(&JFS_SBI(sb)->logpxd); @@ -1114,7 +1115,6 @@ goto errout10; } - log->sb = sb; /* This should be a list */ log->bdev = bdev; memcpy(log->uuid, JFS_SBI(sb)->loguuid, sizeof(log->uuid)); @@ -1813,7 +1813,7 @@ bio->bi_end_io = lbmIODone; bio->bi_private = bp; submit_bio(READ, bio); - run_task_queue(&tq_disk); + blk_run_queues(); wait_event(bp->l_ioevent, (bp->l_flag != lbmREAD)); @@ -1958,7 +1958,7 @@ submit_bio(WRITE, bio); INCREMENT(lmStat.submitted); - run_task_queue(&tq_disk); + blk_run_queues(); jFYI(1, ("lbmStartIO done\n")); } diff -Nru a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c --- a/fs/jfs/jfs_metapage.c Sun Jun 2 18:44:56 2002 +++ b/fs/jfs/jfs_metapage.c Sun Jun 2 18:44:56 2002 @@ -242,13 +242,10 @@ mp->hash_prev = NULL; mp->hash_next = *hash_ptr; *hash_ptr = mp; - list_add(&mp->inode_list, &JFS_IP(mp->mapping->host)->mp_list); } static void remove_from_hash(metapage_t * mp, metapage_t ** hash_ptr) { - list_del(&mp->inode_list); - if (mp->hash_prev) mp->hash_prev->hash_next = mp->hash_next; else { @@ -382,6 +379,8 @@ mp->page = 0; mp->logical_size = size; add_to_hash(mp, hash_ptr); + if (!absolute) + list_add(&mp->inode_list, &JFS_IP(inode)->mp_list); spin_unlock(&meta_lock); if (new) { @@ -390,11 +389,7 @@ mp->page = grab_cache_page(mapping, page_index); if (!mp->page) { jERROR(1, ("grab_cache_page failed!\n")); - spin_lock(&meta_lock); - remove_from_hash(mp, hash_ptr); - __free_metapage(mp); - spin_unlock(&meta_lock); - return NULL; + goto freeit; } else { INCREMENT(mpStat.pagealloc); unlock_page(mp->page); @@ -402,24 +397,27 @@ } else { jFYI(1, ("__get_metapage: Calling read_cache_page\n")); - mp->page = - read_cache_page(mapping, lblock, - (filler_t *) mapping->a_ops-> - readpage, NULL); + mp->page = read_cache_page(mapping, lblock, + (filler_t *)mapping->a_ops->readpage, NULL); if (IS_ERR(mp->page)) { jERROR(1, ("read_cache_page failed!\n")); - spin_lock(&meta_lock); - remove_from_hash(mp, hash_ptr); - __free_metapage(mp); - spin_unlock(&meta_lock); - return NULL; + goto freeit; } else INCREMENT(mpStat.pagealloc); } - mp->data = (void *) (kmap(mp->page) + page_offset); + mp->data = kmap(mp->page) + page_offset; } jFYI(1, ("__get_metapage: returning = 0x%p\n", mp)); return mp; + +freeit: + spin_lock(&meta_lock); + remove_from_hash(mp, hash_ptr); + if (!absolute) + list_del(&mp->inode_list); + __free_metapage(mp); + spin_unlock(&meta_lock); + return NULL; } void hold_metapage(metapage_t * mp, int force) @@ -523,6 +521,8 @@ spin_unlock(&meta_lock); } else { remove_from_hash(mp, meta_hash(mp->mapping, mp->index)); + if (!test_bit(META_absolute, &mp->flag)) + list_del(&mp->inode_list); spin_unlock(&meta_lock); if (mp->page) { @@ -537,7 +537,7 @@ if (test_bit(META_discard, &mp->flag)) { lock_page(mp->page); - block_flushpage(mp->page, 0); + block_invalidatepage(mp->page, 0); unlock_page(mp->page); } @@ -586,17 +586,14 @@ if (mp) { set_bit(META_discard, &mp->flag); spin_unlock(&meta_lock); - /* - * If in the metapage cache, we've got the page locked - */ lock_page(mp->page); - block_flushpage(mp->page, 0); + block_invalidatepage(mp->page, 0); unlock_page(mp->page); } else { spin_unlock(&meta_lock); page = find_lock_page(mapping, lblock>>l2BlocksPerPage); if (page) { - block_flushpage(page, 0); + block_invalidatepage(page, 0); unlock_page(page); } } diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c --- a/fs/jfs/jfs_txnmgr.c Sun Jun 2 18:44:56 2002 +++ b/fs/jfs/jfs_txnmgr.c Sun Jun 2 18:44:56 2002 @@ -720,6 +720,8 @@ le16_to_cpu(p->header.nextindex); } xtlck->lwm.length = 0; /* ! */ + xtlck->twm.offset = 0; + xtlck->hwm.offset = 0; xtlck->index = 2; break; @@ -1868,6 +1870,7 @@ */ if (tlck->type & tlckTRUNCATE) { pxd_t tpxd; /* truncated extent of xad */ + int twm; /* * For truncation the entire linelock may be used, so it would @@ -1881,6 +1884,7 @@ if (lwm == 0) lwm = XTPAGEMAXSLOT; hwm = xtlck->hwm.offset; + twm = xtlck->twm.offset; /* * write log records @@ -1906,9 +1910,9 @@ } /* - * truncate entry XAD[hwm == next - 1]: + * truncate entry XAD[twm == next - 1]: */ - if (hwm == next - 1) { + if (twm == next - 1) { /* init LOG_UPDATEMAP for logredo() to update bmap for * free of truncated delta extent of the truncated * entry XAD[next - 1]: @@ -1975,9 +1979,9 @@ } /* - * truncate entry XAD[hwm == next - 1]: + * truncate entry XAD[twm == next - 1]: */ - if (hwm == next - 1) { + if (twm == next - 1) { pxdlock_t *pxdlock; /* format a maplock for txUpdateMap() to update bmap diff -Nru a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c --- a/fs/jfs/jfs_xtree.c Sun Jun 2 18:44:57 2002 +++ b/fs/jfs/jfs_xtree.c Sun Jun 2 18:44:57 2002 @@ -3574,6 +3574,7 @@ min(index, (int)xtlck->lwm.offset) : index; xtlck->lwm.length = index + 1 - xtlck->lwm.offset; + xtlck->twm.offset = index; pxdlock = (pxdlock_t *) & xtlck->pxdlock; pxdlock->flag = mlckFREEPXD; PXDaddress(&pxdlock->pxd, xaddr); @@ -3705,7 +3706,6 @@ */ tlck = txLock(tid, ip, mp, tlckXTREE); xtlck = (xtlock_t *) & tlck->lock; - xtlck->twm.offset = index; if (!(tlck->type & tlckTRUNCATE)) { xtlck->hwm.offset = le16_to_cpu(p->header. @@ -3782,7 +3782,6 @@ */ tlck = txLock(tid, ip, mp, tlckXTREE); xtlck = (xtlock_t *) & tlck->lock; - xtlck->twm.offset = index; xtlck->hwm.offset = le16_to_cpu(p->header.nextindex) - 1; tlck->type = tlckXTREE | tlckFREE; @@ -3989,11 +3988,10 @@ return (xoff + xlen) << JFS_SBI(ip->i_sb)->l2bsize; } tlck = txLock(tid, ip, mp, tlckXTREE); - tlck->type = tlckXTREE | tlckTRUNCATE; + tlck->type = tlckXTREE | tlckFREE; xtlck = (xtlock_t *) & tlck->lock; xtlck->hwm.offset = index; - tlck->type = tlckXTREE | tlckFREE; XT_PUTPAGE(mp); @@ -4024,7 +4022,6 @@ */ tlck = txLock(tid, ip, mp, tlckXTREE); xtlck = (xtlock_t *) & tlck->lock; - xtlck->twm.offset = index; xtlck->hwm.offset = le16_to_cpu(p->header.nextindex) - 1; tlck->type = tlckXTREE | tlckFREE; diff -Nru a/fs/jfs/namei.c b/fs/jfs/namei.c --- a/fs/jfs/namei.c Sun Jun 2 18:44:58 2002 +++ b/fs/jfs/namei.c Sun Jun 2 18:44:58 2002 @@ -32,6 +32,7 @@ extern int jfs_fsync(struct file *, struct dentry *, int); extern void jfs_truncate_nolock(struct inode *, loff_t); +extern struct inode *jfs_iget(struct super_block *, ino_t); /* * forward references @@ -1410,7 +1411,7 @@ } } - ip = iget(dip->i_sb, inum); + ip = jfs_iget(dip->i_sb, inum); if (ip == NULL) { jERROR(1, ("jfs_lookup: iget failed on inum %d\n", @@ -1418,9 +1419,25 @@ return ERR_PTR(-EACCES); } - d_add(dentry, ip); + return d_splice_alias(ip, dentry); +} + +struct dentry *jfs_get_parent(struct dentry *dentry) +{ + struct super_block *sb = dentry->d_inode->i_sb; + struct dentry *parent = ERR_PTR(-EACCES); + struct inode *inode; + + inode = jfs_iget(sb, JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot); + if (inode) { + parent = d_alloc_anon(inode); + if (!parent) { + parent = ERR_PTR(-ENOMEM); + iput(inode); + } + } - return ERR_PTR(0); + return parent; } struct inode_operations jfs_dir_inode_operations = { diff -Nru a/fs/jfs/super.c b/fs/jfs/super.c --- a/fs/jfs/super.c Sun Jun 2 18:44:57 2002 +++ b/fs/jfs/super.c Sun Jun 2 18:44:57 2002 @@ -53,6 +53,8 @@ /* * External declarations */ +extern struct inode *jfs_iget(struct super_block *, ino_t); + extern int jfs_mount(struct super_block *); extern int jfs_mount_rw(struct super_block *, int); extern int jfs_umount(struct super_block *); @@ -61,12 +63,13 @@ extern int jfsIOWait(void *); extern int jfs_lazycommit(void *); extern int jfs_sync(void *); -extern void jfs_put_inode(struct inode *inode); -extern void jfs_read_inode(struct inode *inode); + extern void jfs_dirty_inode(struct inode *inode); extern void jfs_delete_inode(struct inode *inode); extern void jfs_write_inode(struct inode *inode, int wait); +extern struct dentry *jfs_get_parent(struct dentry *dentry); + #if defined(CONFIG_JFS_DEBUG) && defined(CONFIG_PROC_FS) extern void jfs_proc_init(void); extern void jfs_proc_clean(void); @@ -158,7 +161,6 @@ sbi->direct_inode = NULL; sbi->direct_mapping = NULL; - JFS_SBI(sb) = 0; kfree(sbi); } @@ -233,19 +235,21 @@ return 0; } -static struct super_operations jfs_sops = { +static struct super_operations jfs_super_operations = { alloc_inode: jfs_alloc_inode, destroy_inode: jfs_destroy_inode, - read_inode: jfs_read_inode, dirty_inode: jfs_dirty_inode, write_inode: jfs_write_inode, - put_inode: jfs_put_inode, delete_inode: jfs_delete_inode, put_super: jfs_put_super, statfs: jfs_statfs, remount_fs: jfs_remount, }; +static struct export_operations jfs_export_operations = { + get_parent: jfs_get_parent, +}; + static int jfs_fill_super(struct super_block *sb, void *data, int silent) { struct jfs_sb_info *sbi; @@ -255,10 +259,10 @@ jFYI(1, ("In jfs_read_super: s_flags=0x%lx\n", sb->s_flags)); sbi = kmalloc(sizeof(struct jfs_sb_info), GFP_KERNEL); - JFS_SBI(sb) = sbi; if (!sbi) return -ENOSPC; memset(sbi, 0, sizeof(struct jfs_sb_info)); + sb->u.generic_sbp = sbi; if (!parse_options((char *)data, sbi)) { kfree(sbi); @@ -269,7 +273,13 @@ * Initialize blocksize to 4K. */ sb_set_blocksize(sb, PSIZE); - sb->s_op = &jfs_sops; + + /* + * Set method vectors. + */ + sb->s_op = &jfs_super_operations; + sb->s_export_op = &jfs_export_operations; + /* * Initialize direct-mapping inode/address-space */ @@ -310,7 +320,7 @@ sb->s_magic = JFS_SUPER_MAGIC; - inode = iget(sb, ROOT_I); + inode = jfs_iget(sb, ROOT_I); if (!inode || is_bad_inode(inode)) goto out_no_root; sb->s_root = d_alloc_root(inode); diff -Nru a/fs/minix/dir.c b/fs/minix/dir.c --- a/fs/minix/dir.c Sun Jun 2 18:44:56 2002 +++ b/fs/minix/dir.c Sun Jun 2 18:44:56 2002 @@ -49,7 +49,7 @@ struct inode *dir = (struct inode *)page->mapping->host; int err = 0; page->mapping->a_ops->commit_write(NULL, page, from, to); - if (IS_SYNC(dir)) + if (IS_DIRSYNC(dir)) err = write_one_page(page, 1); else unlock_page(page); diff -Nru a/fs/minix/namei.c b/fs/minix/namei.c --- a/fs/minix/namei.c Sun Jun 2 18:44:57 2002 +++ b/fs/minix/namei.c Sun Jun 2 18:44:57 2002 @@ -4,7 +4,6 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ -#include /* for block_symlink() */ #include "minix.h" static inline void inc_count(struct inode *inode) @@ -111,7 +110,7 @@ inode->i_mode = S_IFLNK | 0777; minix_set_inode(inode, 0); - err = block_symlink(inode, symname, i); + err = page_symlink(inode, symname, i); if (err) goto out_fail; diff -Nru a/fs/namei.c b/fs/namei.c --- a/fs/namei.c Sun Jun 2 18:44:57 2002 +++ b/fs/namei.c Sun Jun 2 18:44:57 2002 @@ -2136,6 +2136,46 @@ return res; } +int page_symlink(struct inode *inode, const char *symname, int len) +{ + struct address_space *mapping = inode->i_mapping; + struct page *page = grab_cache_page(mapping, 0); + int err = -ENOMEM; + char *kaddr; + + if (!page) + goto fail; + err = mapping->a_ops->prepare_write(NULL, page, 0, len-1); + if (err) + goto fail_map; + kaddr = page_address(page); + memcpy(kaddr, symname, len-1); + mapping->a_ops->commit_write(NULL, page, 0, len-1); + /* + * Notice that we are _not_ going to block here - end of page is + * unmapped, so this will only try to map the rest of page, see + * that it is unmapped (typically even will not look into inode - + * ->i_size will be enough for everything) and zero it out. + * OTOH it's obviously correct and should make the page up-to-date. + */ + if (!PageUptodate(page)) { + err = mapping->a_ops->readpage(NULL, page); + wait_on_page_locked(page); + } else { + unlock_page(page); + } + page_cache_release(page); + if (err < 0) + goto fail; + mark_inode_dirty(inode); + return 0; +fail_map: + unlock_page(page); + page_cache_release(page); +fail: + return err; +} + struct inode_operations page_symlink_inode_operations = { readlink: page_readlink, follow_link: page_follow_link, diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c --- a/fs/nfs/inode.c Sun Jun 2 18:44:58 2002 +++ b/fs/nfs/inode.c Sun Jun 2 18:44:58 2002 @@ -799,11 +799,14 @@ nfs_wait_on_inode(struct inode *inode, int flag) { struct rpc_clnt *clnt = NFS_CLIENT(inode); + struct nfs_inode *nfsi = NFS_I(inode); + int error; if (!(NFS_FLAGS(inode) & flag)) return 0; atomic_inc(&inode->i_count); - error = nfs_wait_event(clnt, inode->i_wait, !(NFS_FLAGS(inode) & flag)); + error = nfs_wait_event(clnt, nfsi->nfs_i_wait, + !(NFS_FLAGS(inode) & flag)); iput(inode); return error; } @@ -922,7 +925,7 @@ NFS_FLAGS(inode) &= ~NFS_INO_STALE; out: NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING; - wake_up(&inode->i_wait); + wake_up(&NFS_I(inode)->nfs_i_wait); out_nowait: unlock_kernel(); return status; @@ -1258,6 +1261,7 @@ nfsi->ndirty = 0; nfsi->ncommit = 0; nfsi->npages = 0; + init_waitqueue_head(&nfsi->nfs_i_wait); } } diff -Nru a/fs/pipe.c b/fs/pipe.c --- a/fs/pipe.c Sun Jun 2 18:44:56 2002 +++ b/fs/pipe.c Sun Jun 2 18:44:56 2002 @@ -22,6 +22,9 @@ * * Reads with count = 0 should always return 0. * -- Julian Bradfield 1999-06-07. + * + * FIFOs and Pipes now generate SIGIO for both readers and writers. + * -- Jeremy Elson 2001-08-16 */ /* Drop the inode semaphore and wait for a pipe event, atomically */ @@ -117,12 +120,14 @@ * room. */ wake_up_interruptible(PIPE_WAIT(*inode)); + kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); if (!PIPE_EMPTY(*inode)) BUG(); goto do_more_read; } /* Signal writers asynchronously that there is more room. */ wake_up_interruptible(PIPE_WAIT(*inode)); + kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); ret = read; out: @@ -215,6 +220,7 @@ * to do idle reschedules. */ wake_up_interruptible(PIPE_WAIT(*inode)); + kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); PIPE_WAITING_WRITERS(*inode)++; pipe_wait(inode); PIPE_WAITING_WRITERS(*inode)--; @@ -228,6 +234,7 @@ /* Signal readers asynchronously that there is more data. */ wake_up_interruptible(PIPE_WAIT(*inode)); + kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); inode->i_ctime = inode->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); @@ -308,6 +315,8 @@ kfree(info); } else { wake_up_interruptible(PIPE_WAIT(*inode)); + kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); + kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); } up(PIPE_SEM(*inode)); @@ -315,14 +324,72 @@ } static int +pipe_read_fasync(int fd, struct file *filp, int on) +{ + struct inode *inode = filp->f_dentry->d_inode; + int retval; + + down(PIPE_SEM(*inode)); + retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode)); + up(PIPE_SEM(*inode)); + + if (retval < 0) + return retval; + + return 0; +} + + +static int +pipe_write_fasync(int fd, struct file *filp, int on) +{ + struct inode *inode = filp->f_dentry->d_inode; + int retval; + + down(PIPE_SEM(*inode)); + retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode)); + up(PIPE_SEM(*inode)); + + if (retval < 0) + return retval; + + return 0; +} + + +static int +pipe_rdwr_fasync(int fd, struct file *filp, int on) +{ + struct inode *inode = filp->f_dentry->d_inode; + int retval; + + down(PIPE_SEM(*inode)); + + retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode)); + + if (retval >= 0) + retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode)); + + up(PIPE_SEM(*inode)); + + if (retval < 0) + return retval; + + return 0; +} + + +static int pipe_read_release(struct inode *inode, struct file *filp) { + pipe_read_fasync(-1, filp, 0); return pipe_release(inode, 1, 0); } static int pipe_write_release(struct inode *inode, struct file *filp) { + pipe_write_fasync(-1, filp, 0); return pipe_release(inode, 0, 1); } @@ -331,6 +398,7 @@ { int decr, decw; + pipe_rdwr_fasync(-1, filp, 0); decr = (filp->f_mode & FMODE_READ) != 0; decw = (filp->f_mode & FMODE_WRITE) != 0; return pipe_release(inode, decr, decw); @@ -383,6 +451,7 @@ ioctl: pipe_ioctl, open: pipe_read_open, release: pipe_read_release, + fasync: pipe_read_fasync, }; struct file_operations write_fifo_fops = { @@ -393,6 +462,7 @@ ioctl: pipe_ioctl, open: pipe_write_open, release: pipe_write_release, + fasync: pipe_write_fasync, }; struct file_operations rdwr_fifo_fops = { @@ -403,6 +473,7 @@ ioctl: pipe_ioctl, open: pipe_rdwr_open, release: pipe_rdwr_release, + fasync: pipe_rdwr_fasync, }; struct file_operations read_pipe_fops = { @@ -413,6 +484,7 @@ ioctl: pipe_ioctl, open: pipe_read_open, release: pipe_read_release, + fasync: pipe_read_fasync, }; struct file_operations write_pipe_fops = { @@ -423,6 +495,7 @@ ioctl: pipe_ioctl, open: pipe_write_open, release: pipe_write_release, + fasync: pipe_write_fasync, }; struct file_operations rdwr_pipe_fops = { @@ -433,6 +506,7 @@ ioctl: pipe_ioctl, open: pipe_rdwr_open, release: pipe_rdwr_release, + fasync: pipe_rdwr_fasync, }; struct inode* pipe_new(struct inode* inode) @@ -453,6 +527,7 @@ PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; PIPE_WAITING_READERS(*inode) = PIPE_WAITING_WRITERS(*inode) = 0; PIPE_RCOUNTER(*inode) = PIPE_WCOUNTER(*inode) = 1; + *PIPE_FASYNC_READERS(*inode) = *PIPE_FASYNC_WRITERS(*inode) = NULL; return inode; fail_page: diff -Nru a/fs/ramfs/inode.c b/fs/ramfs/inode.c --- a/fs/ramfs/inode.c Sun Jun 2 18:44:57 2002 +++ b/fs/ramfs/inode.c Sun Jun 2 18:44:57 2002 @@ -29,7 +29,6 @@ #include #include #include -#include /* for block_symlink() */ #include @@ -235,7 +234,7 @@ inode = ramfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0); if (inode) { int l = strlen(symname)+1; - error = block_symlink(inode, symname, l); + error = page_symlink(inode, symname, l); if (!error) { d_instantiate(dentry, inode); dget(dentry); diff -Nru a/fs/sysv/dir.c b/fs/sysv/dir.c --- a/fs/sysv/dir.c Sun Jun 2 18:44:57 2002 +++ b/fs/sysv/dir.c Sun Jun 2 18:44:57 2002 @@ -42,7 +42,7 @@ int err = 0; page->mapping->a_ops->commit_write(NULL, page, from, to); - if (IS_SYNC(dir)) + if (IS_DIRSYNC(dir)) err = write_one_page(page, 1); else unlock_page(page); diff -Nru a/fs/sysv/namei.c b/fs/sysv/namei.c --- a/fs/sysv/namei.c Sun Jun 2 18:44:58 2002 +++ b/fs/sysv/namei.c Sun Jun 2 18:44:58 2002 @@ -117,7 +117,7 @@ goto out; sysv_set_inode(inode, 0); - err = block_symlink(inode, symname, l); + err = page_symlink(inode, symname, l); if (err) goto out_fail; diff -Nru a/fs/ufs/dir.c b/fs/ufs/dir.c --- a/fs/ufs/dir.c Sun Jun 2 18:44:57 2002 +++ b/fs/ufs/dir.c Sun Jun 2 18:44:57 2002 @@ -356,7 +356,7 @@ dir->i_version = ++event; de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino); mark_buffer_dirty(bh); - if (IS_SYNC(dir)) { + if (IS_DIRSYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer(bh); } @@ -457,7 +457,7 @@ de->d_ino = cpu_to_fs32(sb, inode->i_ino); ufs_set_de_type(sb, de, inode->i_mode); mark_buffer_dirty(bh); - if (IS_SYNC(dir)) { + if (IS_DIRSYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); } @@ -508,7 +508,7 @@ inode->i_ctime = inode->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); mark_buffer_dirty(bh); - if (IS_SYNC(inode)) { + if (IS_DIRSYNC(inode)) { ll_rw_block(WRITE, 1, &bh); wait_on_buffer(bh); } diff -Nru a/fs/ufs/namei.c b/fs/ufs/namei.c --- a/fs/ufs/namei.c Sun Jun 2 18:44:58 2002 +++ b/fs/ufs/namei.c Sun Jun 2 18:44:58 2002 @@ -143,7 +143,7 @@ /* slow symlink */ inode->i_op = &page_symlink_inode_operations; inode->i_mapping->a_ops = &ufs_aops; - err = block_symlink(inode, symname, l); + err = page_symlink(inode, symname, l); if (err) goto out_fail; } else { diff -Nru a/fs/ufs/truncate.c b/fs/ufs/truncate.c --- a/fs/ufs/truncate.c Sun Jun 2 18:44:57 2002 +++ b/fs/ufs/truncate.c Sun Jun 2 18:44:57 2002 @@ -453,7 +453,7 @@ break; if (IS_SYNC(inode) && (inode->i_state & I_DIRTY)) ufs_sync_inode (inode); - run_task_queue(&tq_disk); + blk_run_queues(); yield(); } offset = inode->i_size & uspi->s_fshift; diff -Nru a/fs/umsdos/namei.c b/fs/umsdos/namei.c --- a/fs/umsdos/namei.c Sun Jun 2 18:44:58 2002 +++ b/fs/umsdos/namei.c Sun Jun 2 18:44:58 2002 @@ -499,7 +499,7 @@ } len = strlen (symname) + 1; - ret = block_symlink(dentry->d_inode, symname, len); + ret = page_symlink(dentry->d_inode, symname, len); if (ret < 0) goto out_unlink; out: diff -Nru a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h --- a/include/asm-alpha/pgtable.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-alpha/pgtable.h Sun Jun 2 18:44:57 2002 @@ -340,14 +340,11 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) { pte_t pte; pte_val(pte) = (type << 32) | (offset << 40); return pte; } -#define SWP_TYPE(x) (((x).val >> 32) & 0xff) -#define SWP_OFFSET(x) ((x).val >> 40) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) - -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) +#define __swp_type(x) (((x).val >> 32) & 0xff) +#define __swp_offset(x) ((x).val >> 40) +#define __swp_entry(type, offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #ifndef CONFIG_DISCONTIGMEM #define kern_addr_valid(addr) (1) diff -Nru a/include/asm-alpha/siginfo.h b/include/asm-alpha/siginfo.h --- a/include/asm-alpha/siginfo.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-alpha/siginfo.h Sun Jun 2 18:44:57 2002 @@ -6,6 +6,7 @@ #define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 4) #define HAVE_ARCH_COPY_SIGINFO +#define HAVE_ARCH_COPY_SIGINFO_TO_USER #include diff -Nru a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h --- a/include/asm-arm/atomic.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-arm/atomic.h Sun Jun 2 18:44:56 2002 @@ -71,27 +71,27 @@ static __inline__ int atomic_dec_and_test(volatile atomic_t *v) { unsigned long flags; - int result; + int val; __save_flags_cli(flags); - v->counter -= 1; - result = (v->counter == 0); + val = v->counter; + v->counter = val -= 1; __restore_flags(flags); - return result; + return val == 0; } static inline int atomic_add_negative(int i, volatile atomic_t *v) { unsigned long flags; - int result; + int val; __save_flags_cli(flags); - v->counter += i; - result = (v->counter < 0); + val = v->counter; + v->counter = val += i; __restore_flags(flags); - return result; + return val < 0; } static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *addr) diff -Nru a/include/asm-arm/mach/arch.h b/include/asm-arm/mach/arch.h --- a/include/asm-arm/mach/arch.h Sun Jun 2 18:44:58 2002 +++ b/include/asm-arm/mach/arch.h Sun Jun 2 18:44:58 2002 @@ -16,9 +16,6 @@ #ifndef __ASSEMBLY__ -extern void setup_initrd(unsigned int start, unsigned int size); -extern void setup_ramdisk(int doload, int prompt, int start, unsigned int rd_sz); - struct tag; struct machine_desc { diff -Nru a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h --- a/include/asm-arm/pgtable.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-arm/pgtable.h Sun Jun 2 18:44:56 2002 @@ -142,11 +142,11 @@ * * We support up to 32GB of swap on 4k machines */ -#define SWP_TYPE(x) (((x).val >> 2) & 0x7f) -#define SWP_OFFSET(x) ((x).val >> 9) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 9) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(swp) ((pte_t) { (swp).val }) +#define __swp_type(x) (((x).val >> 2) & 0x7f) +#define __swp_offset(x) ((x).val >> 9) +#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 9) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(swp) ((pte_t) { (swp).val }) /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ /* FIXME: this is not correct */ diff -Nru a/include/asm-arm/proc-armo/processor.h b/include/asm-arm/proc-armo/processor.h --- a/include/asm-arm/proc-armo/processor.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-arm/proc-armo/processor.h Sun Jun 2 18:44:56 2002 @@ -23,20 +23,6 @@ #define KERNEL_STACK_SIZE 4096 -struct cpu_context_save { - unsigned long r4; - unsigned long r5; - unsigned long r6; - unsigned long r7; - unsigned long r8; - unsigned long r9; - unsigned long sl; - unsigned long fp; - unsigned long pc; -}; - -#define INIT_CSS (struct cpu_context_save){ 0, 0, 0, 0, 0, 0, 0, 0, SVC26_MODE } - typedef struct { void (*put_byte)(void); /* Special calling convention */ void (*get_byte)(void); /* Special calling convention */ @@ -71,7 +57,7 @@ regs->ARM_r0 = stack[0]; /* r0 (argc) */ \ }) -#define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) -#define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1020]) +#define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1020]) +#define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1018]) #endif diff -Nru a/include/asm-arm/proc-armo/uncompress.h b/include/asm-arm/proc-armo/uncompress.h --- a/include/asm-arm/proc-armo/uncompress.h Sun Jun 2 18:44:57 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,11 +0,0 @@ -/* - * linux/include/asm-arm/proc-armo/uncompress.h - * - * Copyright (C) 1997 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define proc_decomp_setup() diff -Nru a/include/asm-arm/proc-armv/processor.h b/include/asm-arm/proc-armv/processor.h --- a/include/asm-arm/proc-armv/processor.h Sun Jun 2 18:44:58 2002 +++ b/include/asm-arm/proc-armv/processor.h Sun Jun 2 18:44:58 2002 @@ -22,21 +22,6 @@ #define KERNEL_STACK_SIZE PAGE_SIZE -struct cpu_context_save { - unsigned long cpsr; - unsigned long r4; - unsigned long r5; - unsigned long r6; - unsigned long r7; - unsigned long r8; - unsigned long r9; - unsigned long sl; - unsigned long fp; - unsigned long pc; -}; - -#define INIT_CSS (struct cpu_context_save){ SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0 } - #define INIT_EXTRA_THREAD_INFO \ cpu_domain: domain_val(DOMAIN_USER, DOMAIN_CLIENT) | \ domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ @@ -58,7 +43,7 @@ regs->ARM_r0 = stack[0]; /* r0 (argc) */ \ }) -#define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1021]) -#define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) +#define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) +#define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1017]) #endif diff -Nru a/include/asm-arm/proc-armv/uncompress.h b/include/asm-arm/proc-armv/uncompress.h --- a/include/asm-arm/proc-armv/uncompress.h Sun Jun 2 18:44:56 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,26 +0,0 @@ -/* - * linux/include/asm-arm/proc-armv/uncompress.h - * - * Copyright (C) 1997 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -static inline void proc_decomp_setup (void) -{ - __asm__ __volatile__(" - mrc p15, 0, r0, c0, c0 - eor r0, r0, #0x44 << 24 - eor r0, r0, #0x01 << 16 - eor r0, r0, #0xA1 << 8 - movs r0, r0, lsr #5 - mcreq p15, 0, r0, c7, c5, 0 @ flush I cache - mrceq p15, 0, r0, c1, c0 - orreq r0, r0, #1 << 12 - mcreq p15, 0, r0, c1, c0 @ enable I cache - mov r0, #0 - mcreq p15, 0, r0, c15, c1, 2 @ enable clock switching - " : : : "r0", "cc", "memory"); -} diff -Nru a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h --- a/include/asm-arm/thread_info.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-arm/thread_info.h Sun Jun 2 18:44:57 2002 @@ -22,20 +22,35 @@ #include #include -typedef unsigned long mm_segment_t; /* domain register */ +typedef unsigned long mm_segment_t; + +struct cpu_context_save { + __u32 r4; + __u32 r5; + __u32 r6; + __u32 r7; + __u32 r8; + __u32 r9; + __u32 sl; + __u32 fp; + __u32 sp; + __u32 pc; + __u32 extra[2]; /* Xscale 'acc' register, etc */ +}; /* * low level task data that entry.S needs immediate access to. + * We assume cpu_context follows immedately after cpu_domain. */ struct thread_info { unsigned long flags; /* low level flags */ __s32 preempt_count; /* 0 => preemptable, <0 => bug */ mm_segment_t addr_limit; /* address limit */ - __u32 cpu; /* cpu */ - struct cpu_context_save *cpu_context; /* cpu context */ - __u32 cpu_domain; /* cpu domain */ struct task_struct *task; /* main task structure */ struct exec_domain *exec_domain; /* execution domain */ + __u32 cpu; /* cpu */ + __u32 cpu_domain; /* cpu domain */ + struct cpu_context_save cpu_context; /* cpu context */ union fp_state fpstate; }; @@ -71,34 +86,20 @@ #define get_thread_info(ti) get_task_struct((ti)->task) #define put_thread_info(ti) put_task_struct((ti)->task) -static inline unsigned long __thread_saved_pc(struct thread_info *thread) -{ - struct cpu_context_save *context = thread->cpu_context; - - return context ? pc_pointer(context->pc) : 0; -} - -static inline unsigned long __thread_saved_fp(struct thread_info *thread) -{ - struct cpu_context_save *context = thread->cpu_context; - - return context ? context->fp : 0; -} - -#define thread_saved_pc(tsk) __thread_saved_pc((tsk)->thread_info) -#define thread_saved_fp(tsk) __thread_saved_fp((tsk)->thread_info) +#define thread_saved_pc(tsk) (pc_pointer((tsk)->thread_info->cpu_context.pc)) +#define thread_saved_fp(tsk) ((tsk)->thread_info->cpu_context.fp) #else /* !__ASSEMBLY__ */ #define TI_FLAGS 0 #define TI_PREEMPT 4 #define TI_ADDR_LIMIT 8 -#define TI_CPU 12 -#define TI_CPU_SAVE 16 -#define TI_CPU_DOMAIN 20 -#define TI_TASK 24 -#define TI_EXEC_DOMAIN 28 -#define TI_FPSTATE 32 +#define TI_TASK 12 +#define TI_EXEC_DOMAIN 16 +#define TI_CPU 20 +#define TI_CPU_DOMAIN 24 +#define TI_CPU_SAVE 28 +#define TI_FPSTATE 76 #endif diff -Nru a/include/asm-arm/tlb.h b/include/asm-arm/tlb.h --- a/include/asm-arm/tlb.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-arm/tlb.h Sun Jun 2 18:44:56 2002 @@ -1 +1,21 @@ +#ifndef __ASMARM_TLB_H +#define __ASMARM_TLB_H + +#include +#include + +#define tlb_flush(tlb) \ + flush_tlb_mm((tlb)->mm) +#define tlb_start_vma(tlb,vma) \ + flush_cache_range(vma, vma->vm_start, vma->vm_end) +#define tlb_end_vma(tlb,vma) \ + flush_tlb_range(vma, vma->vm_start, vma->vm_end) + +#define tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) + #include + +#define pmd_free_tlb(tlb, pmd) pmd_free(pmd) +#define pte_free_tlb(tlb, pte) pte_free(pte) + +#endif diff -Nru a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h --- a/include/asm-cris/pgtable.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-cris/pgtable.h Sun Jun 2 18:44:56 2002 @@ -500,14 +500,12 @@ /* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */ /* Since the PAGE_PRESENT bit is bit 4, we can use the bits above */ -#define SWP_TYPE(x) (((x).val >> 5) & 0x7f) -#define SWP_OFFSET(x) ((x).val >> 12) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { ((type) << 5) | ((offset) << 12) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 5) & 0x7f) +#define __swp_offset(x) ((x).val >> 12) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 5) | ((offset) << 12) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) #include diff -Nru a/include/asm-cris/siginfo.h b/include/asm-cris/siginfo.h --- a/include/asm-cris/siginfo.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-cris/siginfo.h Sun Jun 2 18:44:57 2002 @@ -1,6 +1,8 @@ #ifndef _CRIS_SIGINFO_H #define _CRIS_SIGINFO_H +#define HAVE_ARCH_COPY_SIGINFO_TO_USER + #include #endif diff -Nru a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h --- a/include/asm-i386/acpi.h Sun Jun 2 18:44:58 2002 +++ b/include/asm-i386/acpi.h Sun Jun 2 18:44:58 2002 @@ -3,7 +3,7 @@ * * Copyright (C) 2001 Paul Diefenbaugh * Copyright (C) 2001 Patrick Mochel - * + * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * This program is free software; you can redistribute it and/or modify @@ -28,48 +28,106 @@ #ifdef __KERNEL__ -#ifdef CONFIG_ACPI_BOOT - -/* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */ -#define FIX_ACPI_PAGES 4 +#define COMPILER_DEPENDENT_INT64 long long +#define COMPILER_DEPENDENT_UINT64 unsigned long long -extern int acpi_mp_config; +/* + * Calling conventions: + * + * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) + * ACPI_EXTERNAL_XFACE - External ACPI interfaces + * ACPI_INTERNAL_XFACE - Internal ACPI interfaces + * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces + */ +#define ACPI_SYSTEM_XFACE +#define ACPI_EXTERNAL_XFACE +#define ACPI_INTERNAL_XFACE +#define ACPI_INTERNAL_VAR_XFACE + +/* Asm macros */ + +#define ACPI_ASM_MACROS +#define BREAKPOINT3 +#define ACPI_DISABLE_IRQS() __cli() +#define ACPI_ENABLE_IRQS() __sti() +#define ACPI_FLUSH_CPU_CACHE() wbinvd() + +/* + * A brief explanation as GNU inline assembly is a bit hairy + * %0 is the output parameter in EAX ("=a") + * %1 and %2 are the input parameters in ECX ("c") + * and an immediate value ("i") respectively + * All actual register references are preceded with "%%" as in "%%edx" + * Immediate values in the assembly are preceded by "$" as in "$0x1" + * The final asm parameter are the operation altered non-output registers. + */ +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ + do { \ + int dummy; \ + asm("1: movl (%1),%%eax;" \ + "movl %%eax,%%edx;" \ + "andl %2,%%edx;" \ + "btsl $0x1,%%edx;" \ + "adcl $0x0,%%edx;" \ + "lock; cmpxchgl %%edx,(%1);" \ + "jnz 1b;" \ + "cmpb $0x3,%%dl;" \ + "sbbl %%eax,%%eax" \ + :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~1L):"dx"); \ + } while(0) + +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ + do { \ + int dummy; \ + asm("1: movl (%1),%%eax;" \ + "movl %%eax,%%edx;" \ + "andl %2,%%edx;" \ + "lock; cmpxchgl %%edx,(%1);" \ + "jnz 1b;" \ + "andl $0x1,%%eax" \ + :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~3L):"dx"); \ + } while(0) -char * __acpi_map_table (unsigned long phys_addr, unsigned long size); -extern int acpi_find_rsdp (unsigned long *phys_addr); -extern int acpi_parse_madt (unsigned long phys_addr, unsigned long size); -extern int acpi_boot_init (char *cmdline); +/* + * Math helper asm macros + */ +#define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) \ + asm("divl %2;" \ + :"=a"(q32), "=d"(r32) \ + :"r"(d32), \ + "0"(n_lo), "1"(n_hi)) + + +#define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \ + asm("shrl $1,%2;" \ + "rcrl $1,%3;" \ + :"=r"(n_hi), "=r"(n_lo) \ + :"0"(n_hi), "1"(n_lo)) + + +#ifndef CONFIG_ACPI_BOOT +#define acpi_lapic 0 +#define acpi_ioapic 0 #else -#define acpi_mp_config 0 -#endif /*CONFIG_ACPI_BOOT*/ +#ifdef CONFIG_X86_LOCAL_APIC +extern int acpi_lapic; +#else +#define acpi_lapic 0 +#endif +#ifdef CONFIG_X86_IO_APIC +extern int acpi_ioapic; +#else +#define acpi_ioapic 0 +#endif -#ifdef CONFIG_ACPI_PCI -int acpi_get_interrupt_model (int *type); -#endif /*CONFIG_ACPI_PCI*/ +/* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */ +#define FIX_ACPI_PAGES 4 +#endif /*CONFIG_ACPI_BOOT*/ #ifdef CONFIG_ACPI_SLEEP -extern unsigned long saved_eip; -extern unsigned long saved_esp; -extern unsigned long saved_ebp; -extern unsigned long saved_ebx; -extern unsigned long saved_esi; -extern unsigned long saved_edi; - -static inline void acpi_save_register_state(unsigned long return_point) -{ - saved_eip = return_point; - asm volatile ("movl %%esp,(%0)" : "=m" (saved_esp)); - asm volatile ("movl %%ebp,(%0)" : "=m" (saved_ebp)); - asm volatile ("movl %%ebx,(%0)" : "=m" (saved_ebx)); - asm volatile ("movl %%edi,(%0)" : "=m" (saved_edi)); - asm volatile ("movl %%esi,(%0)" : "=m" (saved_esi)); -} - -#define acpi_restore_register_state() do {} while (0) - /* routines for saving/restoring kernel state */ extern int acpi_save_state_mem(void); extern int acpi_save_state_disk(void); @@ -81,7 +139,6 @@ extern void acpi_reserve_bootmem(void); #endif /*CONFIG_ACPI_SLEEP*/ - #endif /*__KERNEL__*/ diff -Nru a/include/asm-i386/io_apic.h b/include/asm-i386/io_apic.h --- a/include/asm-i386/io_apic.h Sun Jun 2 18:44:58 2002 +++ b/include/asm-i386/io_apic.h Sun Jun 2 18:44:58 2002 @@ -141,6 +141,13 @@ */ #define io_apic_assign_pci_irqs (mp_irq_entries && !skip_ioapic_setup) +#ifdef CONFIG_ACPI_BOOT +extern int io_apic_get_unique_id (int ioapic, int apic_id); +extern int io_apic_get_version (int ioapic); +extern int io_apic_get_redir_entries (int ioapic); +extern int io_apic_set_pci_routing (int ioapic, int pin, int irq); +#endif /*CONFIG_ACPI_BOOT*/ + #else /* !CONFIG_X86_IO_APIC */ #define io_apic_assign_pci_irqs 0 #endif diff -Nru a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h --- a/include/asm-i386/mpspec.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-i386/mpspec.h Sun Jun 2 18:44:56 2002 @@ -220,5 +220,14 @@ extern int pic_mode; extern int using_apic_timer; +#ifdef CONFIG_ACPI_BOOT +extern void mp_register_lapic (u8 id, u8 enabled); +extern void mp_register_lapic_address (u64 address); +extern void mp_register_ioapic (u8 id, u32 address, u32 irq_base); +extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 global_irq); +extern void mp_config_acpi_legacy_irqs (void); +extern void mp_parse_prt (void); +#endif /*CONFIG_ACPI_BOOT*/ + #endif diff -Nru a/include/asm-i386/page.h b/include/asm-i386/page.h --- a/include/asm-i386/page.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-i386/page.h Sun Jun 2 18:44:56 2002 @@ -30,8 +30,8 @@ #endif -#define clear_user_page(page, vaddr) clear_page(page) -#define copy_user_page(to, from, vaddr) copy_page(to, from) +#define clear_user_page(page, vaddr, pg) clear_page(page) +#define copy_user_page(to, from, vaddr, pg) copy_page(to, from) /* * These are used to make use of C type-checking.. diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h --- a/include/asm-i386/pgtable.h Sun Jun 2 18:44:58 2002 +++ b/include/asm-i386/pgtable.h Sun Jun 2 18:44:58 2002 @@ -269,16 +269,14 @@ #define update_mmu_cache(vma,address,pte) do { } while (0) /* Encode and de-code a swap entry */ -#define SWP_TYPE(x) (((x).val >> 1) & 0x3f) -#define SWP_OFFSET(x) ((x).val >> 8) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 1) & 0x3f) +#define __swp_offset(x) ((x).val >> 8) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #endif /* !__ASSEMBLY__ */ -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) #define io_remap_page_range remap_page_range diff -Nru a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h --- a/include/asm-ia64/pgtable.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-ia64/pgtable.h Sun Jun 2 18:44:57 2002 @@ -402,14 +402,11 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern void paging_init (void); -#define SWP_TYPE(entry) (((entry).val >> 1) & 0xff) -#define SWP_OFFSET(entry) (((entry).val << 1) >> 10) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { ((type) << 1) | ((long) (offset) << 9) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) - -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) +#define __swp_type(entry) (((entry).val >> 1) & 0xff) +#define __swp_offset(entry) (((entry).val << 1) >> 10) +#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 1) | ((long) (offset) << 9) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #define io_remap_page_range remap_page_range /* XXX is this right? */ diff -Nru a/include/asm-ia64/siginfo.h b/include/asm-ia64/siginfo.h --- a/include/asm-ia64/siginfo.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-ia64/siginfo.h Sun Jun 2 18:44:57 2002 @@ -11,8 +11,8 @@ #define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 4) #define HAVE_ARCH_SIGINFO_T - #define HAVE_ARCH_COPY_SIGINFO +#define HAVE_ARCH_COPY_SIGINFO_TO_USER #include diff -Nru a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h --- a/include/asm-m68k/pgtable.h Sun Jun 2 18:44:58 2002 +++ b/include/asm-m68k/pgtable.h Sun Jun 2 18:44:58 2002 @@ -145,27 +145,25 @@ #ifdef CONFIG_SUN3 /* Macros to (de)construct the fake PTEs representing swap pages. */ -#define SWP_TYPE(x) ((x).val & 0x7F) -#define SWP_OFFSET(x) (((x).val) >> 7) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { ((type) | ((offset) << 7)) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) ((x).val & 0x7F) +#define __swp_offset(x) (((x).val) >> 7) +#define __swp_entry(type,offset) ((swp_entry_t) { ((type) | ((offset) << 7)) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #else /* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */ -#define SWP_TYPE(x) (((x).val >> 1) & 0xff) -#define SWP_OFFSET(x) ((x).val >> 10) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 10) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 1) & 0xff) +#define __swp_offset(x) ((x).val >> 10) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 10) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #endif /* CONFIG_SUN3 */ #endif /* !__ASSEMBLY__ */ -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) #define io_remap_page_range remap_page_range diff -Nru a/include/asm-m68k/siginfo.h b/include/asm-m68k/siginfo.h --- a/include/asm-m68k/siginfo.h Sun Jun 2 18:44:55 2002 +++ b/include/asm-m68k/siginfo.h Sun Jun 2 18:44:55 2002 @@ -2,6 +2,7 @@ #define _M68K_SIGINFO_H #define HAVE_ARCH_SIGINFO_T +#define HAVE_ARCH_COPY_SIGINFO #include @@ -68,6 +69,21 @@ #define si_uid16 _sifields._kill._uid #else #define si_uid _sifields._kill._uid +#endif + +#ifdef __KERNEL__ + +#include + +static inline void copy_siginfo(struct siginfo *to, struct siginfo *from) +{ + if (from->si_code < 0) + memcpy(to, from, sizeof(*to)); + else + /* _sigchld is currently the largest know union member */ + memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld)); +} + #endif /* __KERNEL__ */ #endif diff -Nru a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h --- a/include/asm-mips/pgtable.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-mips/pgtable.h Sun Jun 2 18:44:57 2002 @@ -493,15 +493,12 @@ extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte); -#define SWP_TYPE(x) (((x).val >> 1) & 0x3f) -#define SWP_OFFSET(x) ((x).val >> 8) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 1) & 0x3f) +#define __swp_offset(x) ((x).val >> 8) +#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) /* TLB operations. */ diff -Nru a/include/asm-mips/siginfo.h b/include/asm-mips/siginfo.h --- a/include/asm-mips/siginfo.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-mips/siginfo.h Sun Jun 2 18:44:57 2002 @@ -12,8 +12,8 @@ #define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 4) #define HAVE_ARCH_SIGINFO_T - #define HAVE_ARCH_SIGEVENT_T +#define HAVE_ARCH_COPY_SIGINFO #include @@ -121,5 +121,20 @@ } _sigev_thread; } _sigev_un; } sigevent_t; + +#ifdef __KERNEL__ + +#include + +static inline void copy_siginfo(struct siginfo *to, struct siginfo *from) +{ + if (from->si_code < 0) + memcpy(to, from, sizeof(*to)); + else + /* _sigchld is currently the largest know union member */ + memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld)); +} + +#endif #endif /* _ASM_SIGINFO_H */ diff -Nru a/include/asm-mips64/pgtable.h b/include/asm-mips64/pgtable.h --- a/include/asm-mips64/pgtable.h Sun Jun 2 18:44:58 2002 +++ b/include/asm-mips64/pgtable.h Sun Jun 2 18:44:58 2002 @@ -553,14 +553,12 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) { pte_t pte; pte_val(pte) = (type << 32) | (offset << 40); return pte; } -#define SWP_TYPE(x) (((x).val >> 32) & 0xff) -#define SWP_OFFSET(x) ((x).val >> 40) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 32) & 0xff) +#define __swp_offset(x) ((x).val >> 40) +#define __swp_entry(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #ifndef CONFIG_DISCONTIGMEM #define kern_addr_valid(addr) (1) #endif diff -Nru a/include/asm-mips64/siginfo.h b/include/asm-mips64/siginfo.h --- a/include/asm-mips64/siginfo.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-mips64/siginfo.h Sun Jun 2 18:44:57 2002 @@ -13,6 +13,8 @@ #define HAVE_ARCH_SIGINFO_T #define HAVE_ARCH_SIGEVENT_T +#define HAVE_ARCH_COPY_SIGINFO +#define HAVE_ARCH_COPY_SIGINFO_TO_USER #include @@ -120,5 +122,20 @@ } _sigev_thread; } _sigev_un; } sigevent_t; + +#ifdef __KERNEL__ + +#include + +static inline void copy_siginfo(struct siginfo *to, struct siginfo *from) +{ + if (from->si_code < 0) + memcpy(to, from, sizeof(*to)); + else + /* _sigchld is currently the largest know union member */ + memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld)); +} + +#endif #endif /* _ASM_SIGINFO_H */ diff -Nru a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h --- a/include/asm-parisc/pgtable.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-parisc/pgtable.h Sun Jun 2 18:44:57 2002 @@ -312,14 +312,14 @@ /* Encode and de-code a swap entry */ -#define SWP_TYPE(x) ((x).val & 0x3f) -#define SWP_OFFSET(x) ( (((x).val >> 6) & 0x7) | \ +#define __swp_type(x) ((x).val & 0x3f) +#define __swp_offset(x) ( (((x).val >> 6) & 0x7) | \ (((x).val >> 7) & ~0x7) ) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { (type) | \ +#define __swp_entry(type, offset) ((swp_entry_t) { (type) | \ ((offset & 0x7) << 6) | \ ((offset & ~0x7) << 7) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #define module_map vmalloc #define module_unmap vfree @@ -327,9 +327,6 @@ #include #endif /* !__ASSEMBLY__ */ - -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define io_remap_page_range remap_page_range diff -Nru a/include/asm-parisc/siginfo.h b/include/asm-parisc/siginfo.h --- a/include/asm-parisc/siginfo.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-parisc/siginfo.h Sun Jun 2 18:44:57 2002 @@ -1,6 +1,8 @@ #ifndef _PARISC_SIGINFO_H #define _PARISC_SIGINFO_H +#define HAVE_ARCH_COPY_SIGINFO_TO_USER + #include /* diff -Nru a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h --- a/include/asm-ppc/pgtable.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-ppc/pgtable.h Sun Jun 2 18:44:56 2002 @@ -482,11 +482,11 @@ * must not include the _PAGE_PRESENT bit, or the _PAGE_HASHPTE bit * (if used). -- paulus */ -#define SWP_TYPE(entry) ((entry).val & 0x3f) -#define SWP_OFFSET(entry) ((entry).val >> 6) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { (type) | ((offset) << 6) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 2 }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val << 2 }) +#define __swp_type(entry) ((entry).val & 0x3f) +#define __swp_offset(entry) ((entry).val >> 6) +#define __swp_entry(type, offset) ((swp_entry_t) { (type) | ((offset) << 6) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 2 }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 2 }) /* CONFIG_APUS */ /* For virtual address to physical address conversion */ diff -Nru a/include/asm-ppc64/fcntl.h b/include/asm-ppc64/fcntl.h --- a/include/asm-ppc64/fcntl.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-ppc64/fcntl.h Sun Jun 2 18:44:56 2002 @@ -26,7 +26,7 @@ #define O_DIRECTORY 040000 /* must be a directory */ #define O_NOFOLLOW 0100000 /* don't follow links */ #define O_LARGEFILE 0200000 -#define O_DIRECT 0400000 /* direct disk access hint - currently ignored */ +#define O_DIRECT 0400000 /* direct disk access hint */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get close_on_exec */ diff -Nru a/include/asm-ppc64/hardirq.h b/include/asm-ppc64/hardirq.h --- a/include/asm-ppc64/hardirq.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-ppc64/hardirq.h Sun Jun 2 18:44:56 2002 @@ -26,7 +26,7 @@ #endif unsigned int __local_bh_count; unsigned int __syscall_count; - unsigned long __unused; + unsigned long idle_timestamp; struct task_struct * __ksoftirqd_task; } ____cacheline_aligned irq_cpustat_t; diff -Nru a/include/asm-ppc64/memory.h b/include/asm-ppc64/memory.h --- a/include/asm-ppc64/memory.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-ppc64/memory.h Sun Jun 2 18:44:57 2002 @@ -50,7 +50,7 @@ #define HMT_LOW "\tor 1,1,1 # low priority\n" #define HMT_MEDIUM "\tor 2,2,2 # medium priority\n" -#define HMT_MEDIUM "\tor 3,3,3 # high priority\n" +#define HMT_HIGH "\tor 3,3,3 # high priority\n" #else #define HMT_low() do { } while(0) #define HMT_medium() do { } while(0) diff -Nru a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h --- a/include/asm-ppc64/mmu.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-ppc64/mmu.h Sun Jun 2 18:44:56 2002 @@ -211,18 +211,11 @@ asm volatile("eieio; tlbsync; ptesync": : :"memory"); } -static inline void _tlbiel(unsigned long va, int large) +static inline void _tlbiel(unsigned long va) { asm volatile("ptesync": : :"memory"); - - if (large) { - asm volatile("clrldi %0,%0,16\n\ - tlbiel %0,1" : : "r"(va) : "memory"); - } else { - asm volatile("clrldi %0,%0,16\n\ - tlbiel %0,0" : : "r"(va) : "memory"); - } - + asm volatile("clrldi %0,%0,16\n\ + tlbiel %0" : : "r"(va) : "memory"); asm volatile("ptesync": : :"memory"); } diff -Nru a/include/asm-ppc64/paca.h b/include/asm-ppc64/paca.h --- a/include/asm-ppc64/paca.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-ppc64/paca.h Sun Jun 2 18:44:57 2002 @@ -85,7 +85,8 @@ u8 xProcEnabled; /* 1=soft enabled 0x78 */ u8 xHrdIntCount; /* Count of active hardware interrupts 0x79 */ u8 prof_enabled; /* 1=iSeries profiling enabled 0x7A */ - u8 resv1[5]; /* 0x7B-0x7F */ + u8 stab_cache_pointer; + u8 resv1[4]; /* 0x7B-0x7F */ /*===================================================================================== * CACHE_LINE_2 0x0080 - 0x00FF diff -Nru a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h --- a/include/asm-ppc64/page.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-ppc64/page.h Sun Jun 2 18:44:56 2002 @@ -215,11 +215,12 @@ #define __a2p(x) ((void *) absolute_to_phys(x)) #define __a2v(x) ((void *) __va(absolute_to_phys(x))) -#define virt_to_page(kaddr) (mem_map+(__pa((unsigned long)kaddr) >> PAGE_SHIFT)) +#define pfn_to_page(pfn) (mem_map + (pfn)) +#define page_to_pfn(pfn) ((unsigned long)((pfn) - mem_map)) +#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) -#define VALID_PAGE(page) ((page - mem_map) < max_mapnr) - -#define MAP_NR(addr) (__pa(addr) >> PAGE_SHIFT) +#define pfn_valid(pfn) ((pfn) < max_mapnr) +#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) diff -Nru a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h --- a/include/asm-ppc64/pgtable.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-ppc64/pgtable.h Sun Jun 2 18:44:57 2002 @@ -155,7 +155,7 @@ * for zero-mapped memory areas etc.. */ extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)]; -#define ZERO_PAGE(vaddr) (mem_map + MAP_NR(empty_zero_page)) +#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) #endif /* __ASSEMBLY__ */ /* shift to put page number into pte */ @@ -167,24 +167,16 @@ * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. * - * mk_pte_phys takes a physical address as input - * * mk_pte takes a (struct page *) as input */ +#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) -#define mk_pte_phys(physpage,pgprot) \ -({ \ - pte_t pte; \ - pte_val(pte) = (((physpage)<<(PTE_SHIFT-PAGE_SHIFT)) | pgprot_val(pgprot)); \ - pte; \ -}) - -#define mk_pte(page,pgprot) \ -({ \ - pte_t pte; \ - pte_val(pte) = ((unsigned long)((page) - mem_map) << PTE_SHIFT) | \ - pgprot_val(pgprot); \ - pte; \ +#define pfn_pte(pfn,pgprot) \ +({ \ + pte_t pte; \ + pte_val(pte) = ((unsigned long)(pfn) << PTE_SHIFT) | \ + pgprot_val(pgprot); \ + pte; \ }) #define pte_modify(_pte, newprot) \ @@ -195,8 +187,8 @@ /* pte_clear moved to later in this file */ -#define pte_pagenr(x) ((unsigned long)((pte_val(x) >> PTE_SHIFT))) -#define pte_page(x) (mem_map+pte_pagenr(x)) +#define pte_pfn(x) ((unsigned long)((pte_val(x) >> PTE_SHIFT))) +#define pte_page(x) pfn_to_page(pte_pfn(x)) #define pmd_set(pmdp, ptep) (pmd_val(*(pmdp)) = (__ba_to_bpn(ptep))) #define pmd_none(pmd) (!pmd_val(pmd)) @@ -367,11 +359,11 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); /* Encode and de-code a swap entry */ -#define SWP_TYPE(entry) (((entry).val >> 1) & 0x3f) -#define SWP_OFFSET(entry) ((entry).val >> 8) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> PTE_SHIFT }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val << PTE_SHIFT }) +#define __swp_type(entry) (((entry).val >> 1) & 0x3f) +#define __swp_offset(entry) ((entry).val >> 8) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> PTE_SHIFT }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val << PTE_SHIFT }) /* * kern_addr_valid is intended to indicate whether an address is a valid diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h --- a/include/asm-ppc64/processor.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-ppc64/processor.h Sun Jun 2 18:44:56 2002 @@ -97,7 +97,7 @@ #define FPSCR_VX 0x20000000 /* Invalid operation summary */ #define FPSCR_OX 0x10000000 /* Overflow exception summary */ #define FPSCR_UX 0x08000000 /* Underflow exception summary */ -#define FPSCR_ZX 0x04000000 /* Zero-devide exception summary */ +#define FPSCR_ZX 0x04000000 /* Zero-divide exception summary */ #define FPSCR_XX 0x02000000 /* Inexact exception summary */ #define FPSCR_VXSNAN 0x01000000 /* Invalid op for SNaN */ #define FPSCR_VXISI 0x00800000 /* Invalid op for Inv - Inv */ @@ -651,9 +651,7 @@ unsigned long ksp; /* Kernel stack pointer */ struct pt_regs *regs; /* Pointer to saved register state */ mm_segment_t fs; /* for get_fs() validation */ - signed long last_syscall; double fpr[32]; /* Complete floating point set */ - unsigned long fpscr_pad; /* fpr ... fpscr must be contiguous */ unsigned long fpscr; /* Floating point status */ }; @@ -663,8 +661,8 @@ INIT_SP, /* ksp */ \ (struct pt_regs *)INIT_SP - 1, /* regs */ \ KERNEL_DS, /*fs*/ \ - 0, /* last_syscall */ \ - {0}, 0, 0 \ + {0}, /* fpr */ \ + 0 /* fpscr */ \ } /* diff -Nru a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h --- a/include/asm-ppc64/system.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-ppc64/system.h Sun Jun 2 18:44:57 2002 @@ -55,9 +55,31 @@ #define smp_wmb() __asm__ __volatile__("": : :"memory") #endif /* CONFIG_SMP */ +#ifdef CONFIG_DEBUG_KERNEL +extern void (*debugger)(struct pt_regs *regs); +extern int (*debugger_bpt)(struct pt_regs *regs); +extern int (*debugger_sstep)(struct pt_regs *regs); +extern int (*debugger_iabr_match)(struct pt_regs *regs); +extern int (*debugger_dabr_match)(struct pt_regs *regs); +extern void (*debugger_fault_handler)(struct pt_regs *regs); +#else +#define debugger(regs) do { } while (0) +#define debugger_bpt(regs) 0 +#define debugger_sstep(regs) 0 +#define debugger_iabr_match(regs) 0 +#define debugger_dabr_match(regs) 0 +#define debugger_fault_handler ((void (*)(struct pt_regs *))0) +#endif + #ifdef CONFIG_XMON extern void xmon_irq(int, void *, struct pt_regs *); -extern void xmon(struct pt_regs *excp); + +extern void xmon(struct pt_regs *regs); +extern int xmon_bpt(struct pt_regs *regs); +extern int xmon_sstep(struct pt_regs *regs); +extern int xmon_iabr_match(struct pt_regs *regs); +extern int xmon_dabr_match(struct pt_regs *regs); +extern void (*xmon_fault_handler)(struct pt_regs *regs); #endif extern void print_backtrace(unsigned long *); diff -Nru a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h --- a/include/asm-ppc64/thread_info.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-ppc64/thread_info.h Sun Jun 2 18:44:56 2002 @@ -65,6 +65,8 @@ #endif /* __ASSEMBLY__ */ +#define PREEMPT_ACTIVE 0x4000000 + /* * thread information flag bit numbers */ diff -Nru a/include/asm-ppc64/timex.h b/include/asm-ppc64/timex.h --- a/include/asm-ppc64/timex.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-ppc64/timex.h Sun Jun 2 18:44:57 2002 @@ -18,7 +18,6 @@ << (SHIFT_SCALE-SHIFT_HZ)) / HZ) typedef unsigned long cycles_t; -extern cycles_t cacheflush_time; static inline cycles_t get_cycles(void) { diff -Nru a/include/asm-ppc64/uaccess.h b/include/asm-ppc64/uaccess.h --- a/include/asm-ppc64/uaccess.h Sun Jun 2 18:44:55 2002 +++ b/include/asm-ppc64/uaccess.h Sun Jun 2 18:44:56 2002 @@ -240,7 +240,11 @@ { if (access_ok(VERIFY_WRITE, addr, size)) return __clear_user(addr, size); - return size? -EFAULT: 0; + if ((unsigned long)addr < TASK_SIZE) { + unsigned long over = (unsigned long)addr + size - TASK_SIZE; + return __clear_user(addr, size - over) + over; + } + return size; } extern int __strncpy_from_user(char *dst, const char *src, long count); diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h --- a/include/asm-ppc64/unistd.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-ppc64/unistd.h Sun Jun 2 18:44:56 2002 @@ -230,6 +230,9 @@ #define __NR_lremovexattr 219 #define __NR_fremovexattr 220 #define __NR_futex 221 +#define __NR_tux 222 +#define __NR_sched_setaffinity 223 +#define __NR_sched_getaffinity 224 #if 0 /* Remind paulus to add these into ppc32 */ diff -Nru a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h --- a/include/asm-s390/pgtable.h Sun Jun 2 18:44:58 2002 +++ b/include/asm-s390/pgtable.h Sun Jun 2 18:44:58 2002 @@ -485,17 +485,15 @@ return pte; } -#define SWP_TYPE(entry) (((entry).val >> 1) & 0x3f) -#define SWP_OFFSET(entry) (((entry).val >> 12) & 0x7FFFF ) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) +#define __swp_type(entry) (((entry).val >> 1) & 0x3f) +#define __swp_offset(entry) (((entry).val >> 12) & 0x7FFFF ) +#define __swp_entry(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #endif /* !__ASSEMBLY__ */ -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) /* diff -Nru a/include/asm-s390x/pgtable.h b/include/asm-s390x/pgtable.h --- a/include/asm-s390x/pgtable.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-s390x/pgtable.h Sun Jun 2 18:44:57 2002 @@ -505,17 +505,15 @@ return pte; } -#define SWP_TYPE(entry) (((entry).val >> 1) & 0x3f) -#define SWP_OFFSET(entry) ((entry).val >> 12) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) +#define __swp_type(entry) (((entry).val >> 1) & 0x3f) +#define __swp_offset(entry) ((entry).val >> 12) +#define __swp_entry(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #endif /* !__ASSEMBLY__ */ -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) /* diff -Nru a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h --- a/include/asm-sh/pgtable.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-sh/pgtable.h Sun Jun 2 18:44:57 2002 @@ -294,11 +294,11 @@ * NOTE: We should set ZEROs at the position of _PAGE_PRESENT * and _PAGE_PROTONOE bits */ -#define SWP_TYPE(x) ((x).val & 0xff) -#define SWP_OFFSET(x) ((x).val >> 10) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { (type) | ((offset) << 10) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) ((x).val & 0xff) +#define __swp_offset(x) ((x).val >> 10) +#define __swp_entry(type, offset) ((swp_entry_t) { (type) | ((offset) << 10) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) /* * Routines for update of PTE @@ -312,8 +312,6 @@ #endif /* !__ASSEMBLY__ */ -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) #define io_remap_page_range remap_page_range diff -Nru a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h --- a/include/asm-sparc/pgtable.h Sun Jun 2 18:44:57 2002 +++ b/include/asm-sparc/pgtable.h Sun Jun 2 18:44:57 2002 @@ -376,11 +376,11 @@ extern int invalid_segment; /* Encode and de-code a swap entry */ -#define SWP_TYPE(x) (((x).val >> 2) & 0x7f) -#define SWP_OFFSET(x) (((x).val >> 9) & 0x3ffff) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { (((type) & 0x7f) << 2) | (((offset) & 0x3ffff) << 9) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 2) & 0x7f) +#define __swp_offset(x) (((x).val >> 9) & 0x3ffff) +#define __swp_entry(type,offset) ((swp_entry_t) { (((type) & 0x7f) << 2) | (((offset) & 0x3ffff) << 9) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) struct ctx_list { struct ctx_list *next; diff -Nru a/include/asm-sparc/siginfo.h b/include/asm-sparc/siginfo.h --- a/include/asm-sparc/siginfo.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-sparc/siginfo.h Sun Jun 2 18:44:56 2002 @@ -7,6 +7,7 @@ #define HAVE_ARCH_SIGINFO_T #define HAVE_ARCH_COPY_SIGINFO +#define HAVE_ARCH_COPY_SIGINFO_TO_USER #include diff -Nru a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h --- a/include/asm-sparc64/pgtable.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-sparc64/pgtable.h Sun Jun 2 18:44:56 2002 @@ -298,16 +298,16 @@ } /* Encode and de-code a swap entry */ -#define SWP_TYPE(entry) (((entry).val >> PAGE_SHIFT) & 0xffUL) -#define SWP_OFFSET(entry) ((entry).val >> (PAGE_SHIFT + 8UL)) -#define SWP_ENTRY(type, offset) \ +#define __swp_type(entry) (((entry).val >> PAGE_SHIFT) & 0xffUL) +#define __swp_offset(entry) ((entry).val >> (PAGE_SHIFT + 8UL)) +#define __swp_entry(type, offset) \ ( (swp_entry_t) \ { \ (((long)(type) << PAGE_SHIFT) | \ ((long)(offset) << (PAGE_SHIFT + 8UL))) \ } ) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) extern unsigned long prom_virt_to_phys(unsigned long, int *); diff -Nru a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h --- a/include/asm-sparc64/siginfo.h Sun Jun 2 18:44:58 2002 +++ b/include/asm-sparc64/siginfo.h Sun Jun 2 18:44:58 2002 @@ -8,8 +8,8 @@ #define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3) #define HAVE_ARCH_SIGINFO_T - #define HAVE_ARCH_COPY_SIGINFO +#define HAVE_ARCH_COPY_SIGINFO_TO_USER #include diff -Nru a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h --- a/include/asm-x86_64/pgtable.h Sun Jun 2 18:44:56 2002 +++ b/include/asm-x86_64/pgtable.h Sun Jun 2 18:44:56 2002 @@ -329,16 +329,14 @@ #define update_mmu_cache(vma,address,pte) do { } while (0) /* Encode and de-code a swap entry */ -#define SWP_TYPE(x) (((x).val >> 1) & 0x3f) -#define SWP_OFFSET(x) ((x).val >> 8) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 1) & 0x3f) +#define __swp_offset(x) ((x).val >> 8) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #endif /* !__ASSEMBLY__ */ -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) #define io_remap_page_range remap_page_range diff -Nru a/include/linux/acpi.h b/include/linux/acpi.h --- a/include/linux/acpi.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/acpi.h Sun Jun 2 18:44:56 2002 @@ -29,22 +29,28 @@ #define _LINUX #endif +#include + /* - * YES this is ugly. - * But, moving all of ACPI's private headers to include/acpi isn't the right - * answer either. - * Please just ignore it for now. + * Yes this is ugly, but moving all of ACPI's private headers to include/acpi + * isn't the right answer either. Please just ignore it for now. */ #include "../../drivers/acpi/include/acpi.h" #include -/* -------------------------------------------------------------------------- - Boot-Time Table Parsing - -------------------------------------------------------------------------- */ - #ifdef CONFIG_ACPI_BOOT +enum acpi_irq_model_id { + ACPI_IRQ_MODEL_PIC = 0, + ACPI_IRQ_MODEL_IOAPIC, + ACPI_IRQ_MODEL_IOSAPIC, + ACPI_IRQ_MODEL_COUNT +}; + +extern enum acpi_irq_model_id acpi_irq_model; + + /* Root System Description Pointer (RSDP) */ struct acpi_table_rsdp { @@ -327,10 +333,9 @@ typedef int (*acpi_madt_entry_handler) (acpi_table_entry_header *header); -struct acpi_boot_flags { - u8 madt:1; - u8 reserved:7; -}; +char * __acpi_map_table (unsigned long phys_addr, unsigned long size); +unsigned long acpi_find_rsdp (void); +int acpi_boot_init (char *cmdline); int acpi_table_init (char *cmdline); int acpi_table_parse (enum acpi_table_id, acpi_table_handler); @@ -338,31 +343,26 @@ void acpi_table_print (struct acpi_table_header *, unsigned long); void acpi_table_print_madt_entry (acpi_table_entry_header *); -#endif /*CONFIG_ACPI_BOOT*/ +extern int acpi_mp_config; +#else /*!CONFIG_ACPI_BOOT*/ -/* -------------------------------------------------------------------------- - PCI Interrupt Routing (PRT) - -------------------------------------------------------------------------- */ +#define acpi_mp_config 0 -#ifdef CONFIG_ACPI_PCI +#endif /*CONFIG_ACPI_BOOT*/ -#define ACPI_INT_MODEL_PIC 0 -#define ACPI_INT_MODEL_IOAPIC 1 -#define ACPI_INT_MODEL_IOSAPIC 2 + +#ifdef CONFIG_ACPI_PCI struct acpi_prt_entry { struct list_head node; - struct { - u8 seg; - u8 bus; - u8 dev; - u8 pin; - } id; + acpi_pci_id id; + u8 pin; struct { acpi_handle handle; u32 index; - } source; + } link; + u32 irq; }; struct acpi_prt_list { @@ -370,25 +370,21 @@ struct list_head entries; }; -extern struct acpi_prt_list acpi_prts; +extern struct acpi_prt_list acpi_prt; struct pci_dev; -int acpi_prt_get_irq (struct pci_dev *dev, u8 pin, int *irq); -int acpi_prt_set_irq (struct pci_dev *dev, u8 pin, int irq); +int acpi_pci_irq_enable (struct pci_dev *dev); +int acpi_pci_irq_init (void); #endif /*CONFIG_ACPI_PCI*/ -/* -------------------------------------------------------------------------- - ACPI Interpreter (Core) - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_ACPI_INTERPRETER +#ifdef CONFIG_ACPI int acpi_init(void); -#endif /*CONFIG_ACPI_INTERPRETER*/ +#endif /*CONFIG_ACPI*/ #endif /*_LINUX_ACPI_H*/ diff -Nru a/include/linux/adfs_fs.h b/include/linux/adfs_fs.h --- a/include/linux/adfs_fs.h Sun Jun 2 18:44:58 2002 +++ b/include/linux/adfs_fs.h Sun Jun 2 18:44:58 2002 @@ -42,6 +42,7 @@ #ifdef __KERNEL__ #include +#include /* * Calculate the boot block checksum on an ADFS drive. Note that this will * appear to be correct if the sector contains all zeros, so also check that @@ -58,6 +59,11 @@ } while (p != ptr); return (result & 0xff) != ptr[511]; +} + +static inline struct adfs_sb_info *ADFS_SB(struct super_block *sb) +{ + return sb->u.generic_sbp; } static inline struct adfs_inode_info *ADFS_I(struct inode *inode) diff -Nru a/include/linux/agp_backend.h b/include/linux/agp_backend.h --- a/include/linux/agp_backend.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/agp_backend.h Sun Jun 2 18:44:56 2002 @@ -48,10 +48,12 @@ INTEL_I815, INTEL_I820, INTEL_I830_M, + INTEL_I845_G, INTEL_I840, INTEL_I845, INTEL_I850, INTEL_I860, + INTEL_460GX, VIA_GENERIC, VIA_VP3, VIA_MVP3, diff -Nru a/include/linux/atapi.h b/include/linux/atapi.h --- a/include/linux/atapi.h Sun Jun 2 18:44:57 2002 +++ b/include/linux/atapi.h Sun Jun 2 18:44:57 2002 @@ -20,6 +20,19 @@ #define IDEFLOPPY_PC_BUFFER_SIZE 256 #define IDETAPE_PC_BUFFER_SIZE 256 +/* + * Packet flags bits. + */ + +#define PC_ABORT 0 /* set when an error is considered normal - we won't retry */ +#define PC_WAIT_FOR_DSC 1 /* 1 when polling for DSC on a media access command */ +#define PC_DMA_RECOMMENDED 2 /* 1 when we prefer to use DMA if possible */ +#define PC_DMA_IN_PROGRESS 3 /* 1 while DMA in progress */ +#define PC_DMA_ERROR 4 /* 1 when encountered problem during DMA */ +#define PC_WRITING 5 /* data direction */ +#define PC_SUPPRESS_ERROR 6 /* suppress error reporting */ +#define PC_TRANSFORM 7 /* transform SCSI commands */ + /* This struct get's shared between different drivers. */ struct atapi_packet_command { diff -Nru a/include/linux/blk.h b/include/linux/blk.h --- a/include/linux/blk.h Sun Jun 2 18:44:57 2002 +++ b/include/linux/blk.h Sun Jun 2 18:44:57 2002 @@ -125,7 +125,6 @@ static void floppy_off(unsigned int nr); #define DEVICE_NAME "floppy" -#define DEVICE_INTR do_floppy #define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 )) #elif (MAJOR_NR == HD_MAJOR) @@ -149,14 +148,14 @@ #elif (MAJOR_NR == SCSI_TAPE_MAJOR) #define DEVICE_NAME "scsitape" -#define DEVICE_INTR do_st +#define DEVICE_INTR do_st #define DEVICE_NR(device) (minor(device) & 0x7f) #elif (MAJOR_NR == OSST_MAJOR) -#define DEVICE_NAME "onstream" +#define DEVICE_NAME "onstream" #define DEVICE_INTR do_osst -#define DEVICE_NR(device) (minor(device) & 0x7f) +#define DEVICE_NR(device) (minor(device) & 0x7f) #elif (MAJOR_NR == SCSI_CDROM_MAJOR) @@ -187,33 +186,16 @@ #elif (MAJOR_NR == MITSUMI_CDROM_MAJOR) #define DEVICE_NAME "Mitsumi CD-ROM" -/* #define DEVICE_INTR do_mcd */ #define DEVICE_NR(device) (minor(device)) #elif (MAJOR_NR == MITSUMI_X_CDROM_MAJOR) #define DEVICE_NAME "Mitsumi CD-ROM" -/* #define DEVICE_INTR do_mcdx */ #define DEVICE_NR(device) (minor(device)) #elif (MAJOR_NR == MATSUSHITA_CDROM_MAJOR) -#define DEVICE_NAME "Matsushita CD-ROM controller #1" -#define DEVICE_NR(device) (minor(device)) - -#elif (MAJOR_NR == MATSUSHITA_CDROM2_MAJOR) - -#define DEVICE_NAME "Matsushita CD-ROM controller #2" -#define DEVICE_NR(device) (minor(device)) - -#elif (MAJOR_NR == MATSUSHITA_CDROM3_MAJOR) - -#define DEVICE_NAME "Matsushita CD-ROM controller #3" -#define DEVICE_NR(device) (minor(device)) - -#elif (MAJOR_NR == MATSUSHITA_CDROM4_MAJOR) - -#define DEVICE_NAME "Matsushita CD-ROM controller #4" +#define DEVICE_NAME "Matsushita CD-ROM controller" #define DEVICE_NR(device) (minor(device)) #elif (MAJOR_NR == AZTECH_CDROM_MAJOR) @@ -292,27 +274,23 @@ #if (MAJOR_NR != SCSI_TAPE_MAJOR) && (MAJOR_NR != OSST_MAJOR) #if !defined(IDE_DRIVER) -#ifndef CURRENT -# define CURRENT elv_next_request(&blk_dev[MAJOR_NR].request_queue) -#endif #ifndef QUEUE # define QUEUE (&blk_dev[MAJOR_NR].request_queue) #endif +#ifndef CURRENT +# define CURRENT elv_next_request(QUEUE) +#endif #ifndef DEVICE_NAME # define DEVICE_NAME "unknown" #endif #ifdef DEVICE_INTR static void (*DEVICE_INTR)(void) = NULL; -#endif - -#define SET_INTR(x) (DEVICE_INTR = (x)) - -# ifdef DEVICE_INTR -# define CLEAR_INTR SET_INTR(NULL) +# define CLEAR_INTR DEVICE_INTR = NULL # else # define CLEAR_INTR # endif + #endif /* !defined(IDE_DRIVER) */ /* diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h --- a/include/linux/blkdev.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/blkdev.h Sun Jun 2 18:44:56 2002 @@ -81,7 +81,6 @@ /* * for ATA/ATAPI devices */ - __REQ_DRIVE_CMD, __REQ_DRIVE_ACB, __REQ_PC, /* packet command (special) */ @@ -101,7 +100,6 @@ #define REQ_STARTED (1 << __REQ_STARTED) #define REQ_DONTPREP (1 << __REQ_DONTPREP) #define REQ_QUEUED (1 << __REQ_QUEUED) -#define REQ_DRIVE_CMD (1 << __REQ_DRIVE_CMD) #define REQ_DRIVE_ACB (1 << __REQ_DRIVE_ACB) #define REQ_PC (1 << __REQ_PC) #define REQ_BLOCK_PC (1 << __REQ_BLOCK_PC) diff -Nru a/include/linux/buffer_head.h b/include/linux/buffer_head.h --- a/include/linux/buffer_head.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/buffer_head.h Sun Jun 2 18:44:56 2002 @@ -191,8 +191,7 @@ * address_spaces. */ int try_to_release_page(struct page * page, int gfp_mask); -int block_flushpage(struct page *page, unsigned long offset); -int block_symlink(struct inode *, const char *, int); +int block_invalidatepage(struct page *page, unsigned long offset); int block_write_full_page(struct page*, get_block_t*); int block_read_full_page(struct page*, get_block_t*); int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*); diff -Nru a/include/linux/device.h b/include/linux/device.h --- a/include/linux/device.h Sun Jun 2 18:44:57 2002 +++ b/include/linux/device.h Sun Jun 2 18:44:57 2002 @@ -48,13 +48,8 @@ RESUME_ENABLE, }; -enum { - REMOVE_NOTIFY, - REMOVE_FREE_RESOURCES, -}; - struct device; - +struct device_driver; struct bus_type { char * name; @@ -68,6 +63,8 @@ struct driver_dir_entry dir; struct driver_dir_entry device_dir; struct driver_dir_entry driver_dir; + + int (*bind) (struct device * dev, struct device_driver * drv); }; @@ -82,6 +79,11 @@ extern void put_bus(struct bus_type * bus); +extern int bus_for_each_dev(struct bus_type * bus, void * data, + int (*callback)(struct device * dev, void * data)); +extern int bus_for_each_drv(struct bus_type * bus, void * data, + int (*callback)(struct device_driver * drv, void * data)); + struct device_driver { char * name; @@ -96,7 +98,7 @@ struct driver_dir_entry dir; int (*probe) (struct device * dev); - int (*remove) (struct device * dev, u32 flags); + int (*remove) (struct device * dev); int (*suspend) (struct device * dev, u32 state, u32 level); int (*resume) (struct device * dev, u32 level); diff -Nru a/include/linux/ethtool.h b/include/linux/ethtool.h --- a/include/linux/ethtool.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/ethtool.h Sun Jun 2 18:44:56 2002 @@ -4,6 +4,9 @@ * Copyright (C) 1998 David S. Miller (davem@redhat.com) * Copyright 2001 Jeff Garzik * Portions Copyright 2001 Sun Microsystems (thockin@sun.com) + * Portions Copyright 2002 Intel (eli.kupermann@intel.com, + * christopher.leech@intel.com, + * scott.feldman@intel.com) */ #ifndef _LINUX_ETHTOOL_H @@ -268,6 +271,7 @@ * (ethtool_value), priv. */ #define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ #define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ +#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET diff -Nru a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h --- a/include/linux/ext3_fs.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/ext3_fs.h Sun Jun 2 18:44:56 2002 @@ -695,6 +695,7 @@ /* inode.c */ extern struct address_space_operations ext3_aops; +extern struct address_space_operations ext3_writeback_aops; /* namei.c */ extern struct inode_operations ext3_dir_inode_operations; diff -Nru a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h --- a/include/linux/ext3_jbd.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/ext3_jbd.h Sun Jun 2 18:44:56 2002 @@ -299,5 +299,10 @@ return (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA); } +static inline int ext3_should_writeback_data(struct inode *inode) +{ + return !ext3_should_journal_data(inode) && + !ext3_should_order_data(inode); +} #endif /* _LINUX_EXT3_JBD_H */ diff -Nru a/include/linux/fs.h b/include/linux/fs.h --- a/include/linux/fs.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/fs.h Sun Jun 2 18:44:56 2002 @@ -306,7 +306,7 @@ int (*commit_write)(struct file *, struct page *, unsigned, unsigned); /* Unfortunately this kludge is needed for FIBMAP. Don't use it */ int (*bmap)(struct address_space *, long); - int (*flushpage) (struct page *, unsigned long); + int (*invalidatepage) (struct page *, unsigned long); int (*releasepage) (struct page *, int); #define KERNEL_HAS_O_DIRECT /* this is for modules out of the kernel */ int (*direct_IO)(int, struct inode *, struct kiobuf *, unsigned long, int); @@ -383,7 +383,6 @@ struct inode_operations *i_op; struct file_operations *i_fop; /* former ->i_op->default_file_ops */ struct super_block *i_sb; - wait_queue_head_t i_wait; struct file_lock *i_flock; struct address_space *i_mapping; struct address_space i_data; @@ -625,7 +624,6 @@ #include #include #include -#include extern struct list_head super_blocks; extern spinlock_t sb_lock; @@ -671,7 +669,6 @@ struct hpfs_sb_info hpfs_sb; struct ufs_sb_info ufs_sb; struct romfs_sb_info romfs_sb; - struct adfs_sb_info adfs_sb; void *generic_sbp; } u; /* @@ -1247,6 +1244,7 @@ extern int vfs_follow_link(struct nameidata *, const char *); extern int page_readlink(struct dentry *, char *, int); extern int page_follow_link(struct dentry *, struct nameidata *); +extern int page_symlink(struct inode *inode, const char *symname, int len); extern struct inode_operations page_symlink_inode_operations; extern void generic_fillattr(struct inode *, struct kstat *); diff -Nru a/include/linux/hdreg.h b/include/linux/hdreg.h --- a/include/linux/hdreg.h Sun Jun 2 18:44:57 2002 +++ b/include/linux/hdreg.h Sun Jun 2 18:44:57 2002 @@ -74,25 +74,12 @@ #define IDE_DRIVE_TASK_RAW_WRITE 4 struct hd_drive_task_hdr { - u8 data; u8 feature; u8 sector_count; u8 sector_number; u8 low_cylinder; u8 high_cylinder; u8 device_head; - u8 command; -} __attribute__((packed)); - -struct hd_drive_hob_hdr { - u8 data; - u8 feature; - u8 sector_count; - u8 sector_number; - u8 low_cylinder; - u8 high_cylinder; - u8 device_head; - u8 control; } __attribute__((packed)); /* diff -Nru a/include/linux/highmem.h b/include/linux/highmem.h --- a/include/linux/highmem.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/highmem.h Sun Jun 2 18:44:56 2002 @@ -77,7 +77,7 @@ static inline void clear_user_highpage(struct page *page, unsigned long vaddr) { void *addr = kmap_atomic(page, KM_USER0); - clear_user_page(addr, vaddr); + clear_user_page(addr, vaddr, page); kunmap_atomic(addr, KM_USER0); } @@ -111,7 +111,7 @@ vfrom = kmap_atomic(from, KM_USER0); vto = kmap_atomic(to, KM_USER1); - copy_user_page(vto, vfrom, vaddr); + copy_user_page(vto, vfrom, vaddr, to); kunmap_atomic(vfrom, KM_USER0); kunmap_atomic(vto, KM_USER1); } diff -Nru a/include/linux/ide.h b/include/linux/ide.h --- a/include/linux/ide.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/ide.h Sun Jun 2 18:44:56 2002 @@ -38,11 +38,6 @@ # define SUPPORT_SLOW_DATA_PORTS 1 /* 0 to reduce kernel size */ #endif -/* Right now this is only needed by a promise controlled. - */ -#ifndef OK_TO_RESET_CONTROLLER /* 1 needed for good error recovery */ -# define OK_TO_RESET_CONTROLLER 0 /* 0 for use with AH2372A/B interface */ -#endif #ifndef FANCY_STATUS_DUMPS /* 1 for human-readable drive errors */ # define FANCY_STATUS_DUMPS 1 /* 0 to reduce kernel size */ #endif @@ -73,21 +68,22 @@ */ enum { - IDE_DATA_OFFSET = 0, - IDE_ERROR_OFFSET = 1, - IDE_NSECTOR_OFFSET = 2, - IDE_SECTOR_OFFSET = 3, - IDE_LCYL_OFFSET = 4, - IDE_HCYL_OFFSET = 5, - IDE_SELECT_OFFSET = 6, - IDE_STATUS_OFFSET = 7, - IDE_CONTROL_OFFSET = 8, - IDE_IRQ_OFFSET = 9, - IDE_NR_PORTS = 10 + IDE_DATA_OFFSET = 0, + IDE_ERROR_OFFSET = 1, + IDE_FEATURE_OFFSET = 1, + IDE_NSECTOR_OFFSET = 2, + IDE_SECTOR_OFFSET = 3, + IDE_LCYL_OFFSET = 4, + IDE_HCYL_OFFSET = 5, + IDE_SELECT_OFFSET = 6, + IDE_STATUS_OFFSET = 7, + IDE_COMMAND_OFFSET = 7, + IDE_CONTROL_OFFSET = 8, + IDE_ALTSTATUS_OFFSET = 8, + IDE_IRQ_OFFSET = 9, + IDE_NR_PORTS = 10 }; -#define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET -#define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET #define IDE_DATA_REG (drive->channel->io_ports[IDE_DATA_OFFSET]) #define IDE_ERROR_REG (drive->channel->io_ports[IDE_ERROR_OFFSET]) @@ -96,24 +92,18 @@ #define IDE_LCYL_REG (drive->channel->io_ports[IDE_LCYL_OFFSET]) #define IDE_HCYL_REG (drive->channel->io_ports[IDE_HCYL_OFFSET]) #define IDE_SELECT_REG (drive->channel->io_ports[IDE_SELECT_OFFSET]) -#define IDE_STATUS_REG (drive->channel->io_ports[IDE_STATUS_OFFSET]) -#define IDE_CONTROL_REG (drive->channel->io_ports[IDE_CONTROL_OFFSET]) +#define IDE_COMMAND_REG (drive->channel->io_ports[IDE_STATUS_OFFSET]) #define IDE_IRQ_REG (drive->channel->io_ports[IDE_IRQ_OFFSET]) #define IDE_FEATURE_REG IDE_ERROR_REG -#define IDE_COMMAND_REG IDE_STATUS_REG -#define IDE_ALTSTATUS_REG IDE_CONTROL_REG #define IDE_IREASON_REG IDE_NSECTOR_REG #define IDE_BCOUNTL_REG IDE_LCYL_REG #define IDE_BCOUNTH_REG IDE_HCYL_REG #define GET_ERR() IN_BYTE(IDE_ERROR_REG) -#define GET_STAT() IN_BYTE(IDE_STATUS_REG) -#define GET_ALTSTAT() IN_BYTE(IDE_CONTROL_REG) +#define GET_ALTSTAT() IN_BYTE(drive->channel->io_ports[IDE_CONTROL_OFFSET]) #define GET_FEAT() IN_BYTE(IDE_NSECTOR_REG) -#define OK_STAT(stat,good,bad) (((stat)&((good)|(bad)))==(good)) - #define BAD_R_STAT (BUSY_STAT | ERR_STAT) #define BAD_W_STAT (BAD_R_STAT | WRERR_STAT) #define BAD_STAT (BAD_R_STAT | DRQ_STAT) @@ -157,19 +147,6 @@ #define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */ #define WAIT_MIN_SLEEP (2*HZ/100) /* 20msec - minimum sleep time */ -#define SELECT_DRIVE(channel, drive) \ -{ \ - if (channel->selectproc) \ - channel->selectproc(drive); \ - OUT_BYTE((drive)->select.all, channel->io_ports[IDE_SELECT_OFFSET]); \ -} - -#define SELECT_MASK(channel, drive, mask) \ -{ \ - if (channel->maskproc) \ - channel->maskproc(drive,mask); \ -} - /* * Check for an interrupt and acknowledge the interrupt status */ @@ -293,29 +270,6 @@ } b; } select_t; -typedef union { - unsigned all : 8; /* all of the bits together */ - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned bit0 : 1; - unsigned nIEN : 1; /* device INTRQ to host */ - unsigned SRST : 1; /* host soft reset bit */ - unsigned bit3 : 1; /* ATA-2 thingy */ - unsigned reserved456 : 3; - unsigned HOB : 1; /* 48-bit address ordering */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned HOB : 1; - unsigned reserved456 : 3; - unsigned bit3 : 1; - unsigned SRST : 1; - unsigned nIEN : 1; - unsigned bit0 : 1; -#else -#error "Please fix " -#endif - } b; -} control_t; - /* * ATA/ATAPI device structure : */ @@ -359,8 +313,10 @@ unsigned ata_flash : 1; /* 1=present, 0=default */ unsigned addressing; /* : 2; 0=28-bit, 1=48-bit, 2=64-bit */ byte scsi; /* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */ + select_t select; /* basic drive/head select reg value */ - byte ctl; /* "normal" value for IDE_CONTROL_REG */ + u8 status; /* last retrived status value for device */ + byte ready_stat; /* min status value for drive ready */ byte mult_count; /* current multiple sector setting */ byte bad_wstat; /* used for ignoring WRERR_STAT */ @@ -469,7 +425,7 @@ * mode itself. */ - /* setup disk on a channel for a particular transfer mode */ + /* setup disk on a channel for a particular PIO transfer mode */ void (*tuneproc) (struct ata_device *, byte pio); /* setup the chipset timing for a particular transfer mode */ @@ -485,7 +441,7 @@ void (*intrproc) (struct ata_device *); /* special host masking for drive selection */ - void (*maskproc) (struct ata_device *, int); + void (*maskproc) (struct ata_device *); /* check host's drive quirk list */ int (*quirkproc) (struct ata_device *); @@ -499,18 +455,13 @@ void (*atapi_read)(struct ata_device *, void *, unsigned int); void (*atapi_write)(struct ata_device *, void *, unsigned int); - int (*XXX_udma)(struct ata_device *); + int (*udma_setup)(struct ata_device *); void (*udma_enable)(struct ata_device *, int, int); - int (*udma_start) (struct ata_device *, struct request *rq); int (*udma_stop) (struct ata_device *); - - int (*udma_read) (struct ata_device *, struct request *rq); - int (*udma_write) (struct ata_device *, struct request *rq); - + int (*udma_init) (struct ata_device *, struct request *rq); int (*udma_irq_status) (struct ata_device *); - void (*udma_timeout) (struct ata_device *); void (*udma_irq_lost) (struct ata_device *); @@ -551,7 +502,7 @@ * Register new hardware with ide */ extern int ide_register_hw(hw_regs_t *hw); -extern void ide_unregister(struct ata_channel *hwif); +extern void ide_unregister(struct ata_channel *); struct ata_taskfile; @@ -664,25 +615,10 @@ */ extern u8 ide_dump_status(struct ata_device *, struct request *rq, const char *, u8); -extern ide_startstop_t ide_error(struct ata_device *, struct request *rq, - const char *, byte); +extern ide_startstop_t ata_error(struct ata_device *, struct request *rq, const char *); -/* - * ide_fixstring() cleans up and (optionally) byte-swaps a text string, - * removing leading/trailing blanks and compressing internal blanks. - * It is primarily used to tidy up the model name/number fields as - * returned by the WIN_[P]IDENTIFY commands. - */ -void ide_fixstring(byte *s, const int bytecount, const int byteswap); +extern void ide_fixstring(char *s, const int bytecount, const int byteswap); -/* - * This routine busy-waits for the drive status to be not "busy". - * It then checks the status for all of the "good" bits and none - * of the "bad" bits, and if all is okay it returns 0. All other - * cases return 1 after doing "*startstop = ide_error()", and the - * caller should return the updated value of "startstop" in this case. - * "startstop" is unchanged when the function returns 0; - */ extern int ide_wait_stat(ide_startstop_t *, struct ata_device *, struct request *rq, byte, byte, unsigned long); @@ -707,11 +643,6 @@ ide_startstop_t restart_request(struct ata_device *); /* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). - */ -extern void ide_init_drive_cmd(struct request *rq); - -/* * "action" parameter type for ide_do_drive_cmd() below. */ typedef enum { @@ -730,11 +661,12 @@ /* * Clean up after success/failure of an explicit drive cmd. */ -extern void ide_end_drive_cmd(struct ata_device *, struct request *, u8, u8); +extern void ide_end_drive_cmd(struct ata_device *, struct request *); struct ata_taskfile { struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; + struct hd_drive_task_hdr hobfile; + u8 cmd; /* actual ATA command */ int command_type; ide_startstop_t (*prehandler)(struct ata_device *, struct request *); ide_startstop_t (*handler)(struct ata_device *, struct request *); @@ -753,21 +685,18 @@ extern ide_startstop_t recal_intr(struct ata_device *, struct request *); extern ide_startstop_t task_no_data_intr(struct ata_device *, struct request *); - -/* This is setting up all fields in args, which depend upon the command type. - */ extern void ide_cmd_type_parser(struct ata_taskfile *args); extern int ide_raw_taskfile(struct ata_device *, struct ata_taskfile *); -extern int ide_cmd_ioctl(struct ata_device *drive, unsigned long arg); extern void ide_fix_driveid(struct hd_driveid *id); extern int ide_config_drive_speed(struct ata_device *, byte); extern byte eighty_ninty_three(struct ata_device *); -extern int system_bus_speed; extern void ide_stall_queue(struct ata_device *, unsigned long); +extern int system_bus_speed; + /* * CompactFlash cards and their brethern pretend to be removable hard disks, * but they never have a slave unit, and they don't have doorlock mechanisms. @@ -836,14 +765,12 @@ return drive->channel->udma_stop(drive); } -static inline int udma_read(struct ata_device *drive, struct request *rq) -{ - return drive->channel->udma_read(drive, rq); -} - -static inline int udma_write(struct ata_device *drive, struct request *rq) +/* + * Initiate actual DMA data transfer. The direction is encoded in the request. + */ +static inline int udma_init(struct ata_device *drive, struct request *rq) { - return drive->channel->udma_write(drive, rq); + return drive->channel->udma_init(drive, rq); } static inline int udma_irq_status(struct ata_device *drive) @@ -863,14 +790,14 @@ #ifdef CONFIG_BLK_DEV_IDEDMA -void udma_pci_enable(struct ata_device *drive, int on, int verbose); -int udma_pci_start(struct ata_device *drive, struct request *rq); -int udma_pci_stop(struct ata_device *drive); -int udma_pci_read(struct ata_device *drive, struct request *rq); -int udma_pci_write(struct ata_device *drive, struct request *rq); -int udma_pci_irq_status(struct ata_device *drive); -void udma_pci_timeout(struct ata_device *drive); -void udma_pci_irq_lost(struct ata_device *); +extern void udma_pci_enable(struct ata_device *drive, int on, int verbose); +extern int udma_pci_start(struct ata_device *drive, struct request *rq); +extern int udma_pci_stop(struct ata_device *drive); +extern int udma_pci_init(struct ata_device *drive, struct request *rq); +extern int udma_pci_irq_status(struct ata_device *drive); +extern void udma_pci_timeout(struct ata_device *drive); +extern void udma_pci_irq_lost(struct ata_device *); +extern int udma_pci_setup(struct ata_device *); extern int udma_new_table(struct ata_channel *, struct request *); extern void udma_destroy_table(struct ata_channel *); @@ -879,14 +806,11 @@ extern int udma_black_list(struct ata_device *); extern int udma_white_list(struct ata_device *); -extern int ata_do_udma(unsigned int reading, struct ata_device *drive, struct request *rq); - extern ide_startstop_t udma_tcq_taskfile(struct ata_device *, struct request *); extern int udma_tcq_enable(struct ata_device *, int); extern ide_startstop_t ide_dma_intr(struct ata_device *, struct request *); extern int check_drive_lists(struct ata_device *, int good_bad); -extern int XXX_ide_dmaproc(struct ata_device *); extern void ide_release_dma(struct ata_channel *); extern int ata_start_dma(struct ata_device *, struct request *rq); @@ -901,5 +825,14 @@ #define DRIVE_LOCK(drive) ((drive)->queue.queue_lock) extern int drive_is_ready(struct ata_device *drive); + +/* Low level device access functions. */ + +extern void ata_select(struct ata_device *, unsigned long); +extern void ata_mask(struct ata_device *); +extern int ata_status(struct ata_device *, u8, u8); +extern int ata_irq_enable(struct ata_device *, int); +extern void ata_reset(struct ata_channel *); +extern void ata_out_regfile(struct ata_device *, struct hd_drive_task_hdr *); #endif diff -Nru a/include/linux/jbd.h b/include/linux/jbd.h --- a/include/linux/jbd.h Sun Jun 2 18:44:58 2002 +++ b/include/linux/jbd.h Sun Jun 2 18:44:58 2002 @@ -641,7 +641,8 @@ extern void journal_release_buffer (handle_t *, struct buffer_head *); extern void journal_forget (handle_t *, struct buffer_head *); extern void journal_sync_buffer (struct buffer_head *); -extern int journal_flushpage(journal_t *, struct page *, unsigned long); +extern int journal_invalidatepage(journal_t *, + struct page *, unsigned long); extern int journal_try_to_free_buffers(journal_t *, struct page *, int); extern int journal_stop(handle_t *); extern int journal_flush (journal_t *); diff -Nru a/include/linux/list.h b/include/linux/list.h --- a/include/linux/list.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/list.h Sun Jun 2 18:44:56 2002 @@ -94,6 +94,8 @@ static __inline__ void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); + entry->next = (void *) 0; + entry->prev = (void *) 0; } /** diff -Nru a/include/linux/module.h b/include/linux/module.h --- a/include/linux/module.h Sun Jun 2 18:44:58 2002 +++ b/include/linux/module.h Sun Jun 2 18:44:58 2002 @@ -11,17 +11,6 @@ #include #include -#ifdef __GENKSYMS__ -# define _set_ver(sym) sym -# undef MODVERSIONS -# define MODVERSIONS -#else /* ! __GENKSYMS__ */ -# if !defined(MODVERSIONS) && defined(EXPORT_SYMTAB) -# define _set_ver(sym) sym -# include -# endif -#endif /* __GENKSYMS__ */ - #include /* Don't need to bring in all of uaccess.h just for this decl. */ @@ -297,7 +286,7 @@ #include static const char __module_kernel_version[] __attribute__((section(".modinfo"))) = "kernel_version=" UTS_RELEASE; -#ifdef MODVERSIONS +#ifdef CONFIG_MODVERSIONS static const char __module_using_checksums[] __attribute__((section(".modinfo"))) = "using_checksums=1"; #endif @@ -345,6 +334,101 @@ insmod -[xX] flags. Otherwise, only the variables listed are exported. This obviates the need for the old register_symtab() function. */ +/* So how does the CONFIG_MODVERSIONS magic work? + * + * A module can only be loaded if it's undefined symbols can be resolved + * using symbols the kernel exports for that purpose. The idea behind + * CONFIG_MODVERSIONS is to mangle those symbols depending on their + * definition (see man genksyms) - a change in the definition will thus + * caused the mangled name to change, and the module will refuse to + * load due to unresolved symbols. + * + * Let's start with taking a look how things work when we don't use + * CONFIG_MODVERSIONS. In this case, the only thing which is worth + * mentioning is the EXPORT_SYMBOL() macro. Using EXPORT_SYMBOL(foo) + * will expand into __EXPORT_SYMBOL(foo, "foo"), which then uses + * some ELF section magic to generate a list of pairs + * (address, symbol_name), which is used to resolve undefined + * symbols into addresses when loading a module. + * + * That's easy. Let's get back to CONFIG_MODVERSIONS=y. + * + * The first step is to generate the checksums. This is done at + * "make dep" time, code which exports symbols (using EXPORT_SYMTAB) + * is preprocessed with the additional macro __GENKSYMS__ set and fed + * into genksyms. + * At this stage, for each file that exports symbols an corresponding + * file in include/linux/module is generated, which for each exported + * symbol contains + * + * #define __ver_schedule_task 2d6c3d04 + * #define schedule_task _set_ver(schedule_task) + * + * In addition, include/linux/modversions.h is generated, which + * looks like + * + * #include + * #include + * <<>> + * + * Let's see what happens for different cases during compilation. + * + * o compile a file into the kernel which does not export symbols: + * + * Since the file is known to not export symbols (it's not listed + * in the export-objs variable in the corresponding Makefile), the + * kernel build system does compile it with no extra flags set. + * The macro EXPORT_SYMTAB is unset, and you can see below that + * files which still try to use EXPORT_SYMBOL() will be trapped. + * Other than that, just regular compilation. + * + * o compile a file into the kernel which does export symbols: + * + * In this case, the file will compiled with the macro + * EXPORT_SYMTAB defined. + * As MODULE is not set, we hit this case from below: + * + * #define _set_ver(sym) sym + * #include + * + * #define EXPORT_SYMBOL(var) \ + * __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var))) + * + * The first two lines will in essence include + * + * #define __ver_schedule_task 2d6c3d04 + * #define schedule_task schedule_task + * + * for each symbol. The second line really doesn't do much, but the + * first one gives us the checksums we generated before. + * + * So EXPORT_SYMBOL(schedule_task) will expand into + * __EXPORT_SYMBOL(schedule_task, "schedule_task_R2d6c3d04"), + * hence exporting the symbol for schedule_task under the name of + * schedule_task_R2d6c3d04. + * + * o compile a file into a module + * + * In this case, the kernel build system will add + * "-include include/linux/modversions.h" to the command line. So + * modversions.h is prepended to the actual source, turning into + * + * #define __ver_schedule_task 2d6c3d04 + * #define schedule_task schedule_task_R2d6c3d04 + * + * Though the source code says "schedule_task", the compiler will + * see the mangled symbol everywhere. So the module will end up with + * an undefined symbol "schedule_task_R2d6c3d04" - which is exactly + * the symbols which occurs in the kernel's list of symbols, with + * a value of &schedule_task - it all comes together nicely. + * + * One question remains: What happens if a module itself exports + * a symbol - the answer is simple: It's actually handled as the + * CONFIG_MODVERSIONS=n case described first, only that the compiler + * sees the mangled symbol everywhere. So &foo_R12345678 is exported + * with the name "foo_R12345678". Think about it. It all makes sense. + */ + #if defined(__GENKSYMS__) /* We want the EXPORT_SYMBOL tag left intact for recognition. */ @@ -379,13 +463,20 @@ __attribute__((section("__ksymtab"))) = \ { (unsigned long)&sym, __kstrtab_##sym } -#if defined(MODVERSIONS) || !defined(CONFIG_MODVERSIONS) -#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var)) -#define EXPORT_SYMBOL_GPL(var) __EXPORT_SYMBOL_GPL(var, __MODULE_STRING(var)) -#else +#if defined(CONFIG_MODVERSIONS) && !defined(MODULE) + +#define _set_ver(sym) sym +#include + #define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var))) #define EXPORT_SYMBOL_GPL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var))) -#endif + +#else /* !defined (CONFIG_MODVERSIONS) || defined(MODULE) */ + +#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var)) +#define EXPORT_SYMBOL_GPL(var) __EXPORT_SYMBOL_GPL(var, __MODULE_STRING(var)) + +#endif /* defined(CONFIG_MODVERSIONS) && !defined(MODULE) */ #define EXPORT_SYMBOL_NOVERS(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var)) diff -Nru a/include/linux/nbd.h b/include/linux/nbd.h --- a/include/linux/nbd.h Sun Jun 2 18:44:58 2002 +++ b/include/linux/nbd.h Sun Jun 2 18:44:58 2002 @@ -20,6 +20,12 @@ #define NBD_SET_SIZE_BLOCKS _IO( 0xab, 7 ) #define NBD_DISCONNECT _IO( 0xab, 8 ) +enum { + NBD_CMD_READ = 0, + NBD_CMD_WRITE = 1, + NBD_CMD_DISC = 2 +}; + #ifdef MAJOR_NR #include @@ -33,6 +39,8 @@ extern int requests_out; #endif +#define nbd_cmd(req) ((req)->cmd[0]) + static void nbd_end_request(struct request *req) { @@ -68,6 +76,7 @@ struct socket * sock; struct file * file; /* If == NULL, device is not ready, yet */ int magic; /* FIXME: not if debugging is off */ + spinlock_t queue_lock; struct list_head queue_head; /* Requests are added here... */ struct semaphore tx_lock; }; diff -Nru a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h --- a/include/linux/nfs_fs.h Sun Jun 2 18:44:57 2002 +++ b/include/linux/nfs_fs.h Sun Jun 2 18:44:57 2002 @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -158,6 +159,8 @@ /* Credentials for shared mmap */ struct rpc_cred *mm_cred; + + wait_queue_head_t nfs_i_wait; struct inode vfs_inode; }; diff -Nru a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h --- a/include/linux/pipe_fs_i.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/pipe_fs_i.h Sun Jun 2 18:44:56 2002 @@ -13,6 +13,8 @@ unsigned int waiting_writers; unsigned int r_counter; unsigned int w_counter; + struct fasync_struct *fasync_readers; + struct fasync_struct *fasync_writers; }; /* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual @@ -30,6 +32,8 @@ #define PIPE_WAITING_WRITERS(inode) ((inode).i_pipe->waiting_writers) #define PIPE_RCOUNTER(inode) ((inode).i_pipe->r_counter) #define PIPE_WCOUNTER(inode) ((inode).i_pipe->w_counter) +#define PIPE_FASYNC_READERS(inode) (&((inode).i_pipe->fasync_readers)) +#define PIPE_FASYNC_WRITERS(inode) (&((inode).i_pipe->fasync_writers)) #define PIPE_EMPTY(inode) (PIPE_LEN(inode) == 0) #define PIPE_FULL(inode) (PIPE_LEN(inode) == PIPE_SIZE) diff -Nru a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h --- a/include/linux/raid/md_k.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/raid/md_k.h Sun Jun 2 18:44:56 2002 @@ -355,7 +355,7 @@ if (condition) \ break; \ spin_unlock_irq(&lock); \ - run_task_queue(&tq_disk); \ + blk_run_queues(); \ schedule(); \ spin_lock_irq(&lock); \ } \ @@ -381,7 +381,7 @@ set_current_state(TASK_UNINTERRUPTIBLE); \ if (condition) \ break; \ - run_task_queue(&tq_disk); \ + blk_run_queues(); \ schedule(); \ } \ current->state = TASK_RUNNING; \ diff -Nru a/include/linux/sched.h b/include/linux/sched.h --- a/include/linux/sched.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/sched.h Sun Jun 2 18:44:56 2002 @@ -235,7 +235,7 @@ atomic_t files; /* How many open files does this user have? */ /* Hash table maintenance information */ - struct user_struct *next, **pprev; + struct list_head uidhash_list; uid_t uid; }; diff -Nru a/include/linux/swap.h b/include/linux/swap.h --- a/include/linux/swap.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/swap.h Sun Jun 2 18:44:56 2002 @@ -11,7 +11,16 @@ #define SWAP_FLAG_PRIO_MASK 0x7fff #define SWAP_FLAG_PRIO_SHIFT 0 -#define MAX_SWAPFILES 32 +/* + * MAX_SWAPFILES defines the maximum number of swaptypes: things which can + * be swapped to. The swap type and the offset into that swap type are + * encoded into pte's and into pgoff_t's in the swapcache. Using five bits + * for the type means that the maximum number of swapcache pages is 27 bits + * on 32-bit-pgoff_t architectures. And that assumes that the architecture packs + * the type/offset into the pte as 5/27 as well. + */ +#define MAX_SWAPFILES_SHIFT 5 +#define MAX_SWAPFILES (1 << MAX_SWAPFILES_SHIFT) /* * Magic header for a swap area. The first part of the union is diff -Nru a/include/linux/swapops.h b/include/linux/swapops.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/linux/swapops.h Sun Jun 2 18:44:58 2002 @@ -0,0 +1,68 @@ +/* + * swapcache pages are stored in the swapper_space radix tree. We want to + * get good packing density in that tree, so the index should be dense in + * the low-order bits. + * + * We arrange the `type' and `offset' fields so that `type' is at the five + * high-order bits of the smp_entry_t and `offset' is right-aligned in the + * remaining bits. + * + * swp_entry_t's are *never* stored anywhere in their arch-dependent format. + */ +#define SWP_TYPE_SHIFT(e) (sizeof(e.val) * 8 - MAX_SWAPFILES_SHIFT) +#define SWP_OFFSET_MASK(e) ((1 << SWP_TYPE_SHIFT(e)) - 1) + +/* + * Store a type+offset into a swp_entry_t in an arch-independent format + */ +static inline swp_entry_t swp_entry(unsigned type, pgoff_t offset) +{ + swp_entry_t ret; + + ret.val = (type << SWP_TYPE_SHIFT(ret)) | + (offset & SWP_OFFSET_MASK(ret)); + return ret; +} + +/* + * Extract the `type' field from a swp_entry_t. The swp_entry_t is in + * arch-independent format + */ +static inline unsigned swp_type(swp_entry_t entry) +{ + return (entry.val >> SWP_TYPE_SHIFT(entry)) & + ((1 << MAX_SWAPFILES_SHIFT) - 1); +} + +/* + * Extract the `offset' field from a swp_entry_t. The swp_entry_t is in + * arch-independent format + */ +static inline pgoff_t swp_offset(swp_entry_t entry) +{ + return entry.val & SWP_OFFSET_MASK(entry); +} + +/* + * Convert the arch-dependent pte representation of a swp_entry_t into an + * arch-independent swp_entry_t. + */ +static inline swp_entry_t pte_to_swp_entry(pte_t pte) +{ + swp_entry_t arch_entry; + + arch_entry = __pte_to_swp_entry(pte); + return swp_entry(__swp_type(arch_entry), __swp_offset(arch_entry)); +} + +/* + * Convert the arch-independent representation of a swp_entry_t into the + * arch-dependent pte representation. + */ +static inline pte_t swp_entry_to_pte(swp_entry_t entry) +{ + swp_entry_t arch_entry; + + arch_entry = __swp_entry(swp_type(entry), swp_offset(entry)); + return __swp_entry_to_pte(arch_entry); +} diff -Nru a/include/linux/types.h b/include/linux/types.h --- a/include/linux/types.h Sun Jun 2 18:44:57 2002 +++ b/include/linux/types.h Sun Jun 2 18:44:57 2002 @@ -124,6 +124,14 @@ typedef unsigned long sector_t; #endif +/* + * The type of an index into the pagecache. Use a #define so asm/types.h + * can override it. + */ +#ifndef pgoff_t +#define pgoff_t unsigned long +#endif + #endif /* __KERNEL_STRICT_NAMES */ /* diff -Nru a/include/linux/udf_fs.h b/include/linux/udf_fs.h --- a/include/linux/udf_fs.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/udf_fs.h Sun Jun 2 18:44:56 2002 @@ -36,8 +36,6 @@ #include -#include - #define UDF_PREALLOCATE #define UDF_DEFAULT_PREALLOC_BLOCKS 8 diff -Nru a/include/linux/usb.h b/include/linux/usb.h --- a/include/linux/usb.h Sun Jun 2 18:44:57 2002 +++ b/include/linux/usb.h Sun Jun 2 18:44:57 2002 @@ -713,6 +713,8 @@ /* void (*resume)(struct usb_device *dev); */ }; +extern struct bus_type usb_bus_type; + /* * use these in module_init()/module_exit() * and don't forget MODULE_DEVICE_TABLE(usb, ...) diff -Nru a/include/linux/writeback.h b/include/linux/writeback.h --- a/include/linux/writeback.h Sun Jun 2 18:44:56 2002 +++ b/include/linux/writeback.h Sun Jun 2 18:44:56 2002 @@ -31,6 +31,7 @@ void writeback_unlocked_inodes(int *nr_to_write, int sync_mode, unsigned long *older_than_this); +void wake_up_inode(struct inode *inode); void __wait_on_inode(struct inode * inode); void sync_inodes_sb(struct super_block *, int wait); void sync_inodes(int wait); diff -Nru a/init/do_mounts.c b/init/do_mounts.c --- a/init/do_mounts.c Sun Jun 2 18:44:57 2002 +++ b/init/do_mounts.c Sun Jun 2 18:44:57 2002 @@ -365,7 +365,7 @@ return sys_symlink(path + n + 5, name); } -#if defined(BLOCK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD) +#if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD) static void __init change_floppy(char *fmt, ...) { struct termios termios; diff -Nru a/init/main.c b/init/main.c --- a/init/main.c Sun Jun 2 18:44:56 2002 +++ b/init/main.c Sun Jun 2 18:44:56 2002 @@ -51,7 +51,7 @@ * To avoid associated bogus bug reports, we flatly refuse to compile * with a gcc that is known to be too old from the very beginning. */ -#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 91) +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 95) #error Sorry, your GCC is too old. It builds incorrect kernels. #endif diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c --- a/kernel/ksyms.c Sun Jun 2 18:44:56 2002 +++ b/kernel/ksyms.c Sun Jun 2 18:44:56 2002 @@ -277,7 +277,7 @@ EXPORT_SYMBOL(page_readlink); EXPORT_SYMBOL(page_follow_link); EXPORT_SYMBOL(page_symlink_inode_operations); -EXPORT_SYMBOL(block_symlink); +EXPORT_SYMBOL(page_symlink); EXPORT_SYMBOL(vfs_readdir); EXPORT_SYMBOL(__get_lease); EXPORT_SYMBOL(lease_get_mtime); diff -Nru a/kernel/softirq.c b/kernel/softirq.c --- a/kernel/softirq.c Sun Jun 2 18:44:56 2002 +++ b/kernel/softirq.c Sun Jun 2 18:44:56 2002 @@ -151,8 +151,10 @@ struct tasklet_struct *list; }; -static struct tasklet_head tasklet_vec __per_cpu_data; -static struct tasklet_head tasklet_hi_vec __per_cpu_data; +/* Some compilers disobey section attribute on statics when not + initialized -- RR */ +static struct tasklet_head tasklet_vec __per_cpu_data = { NULL }; +static struct tasklet_head tasklet_hi_vec __per_cpu_data = { NULL }; void __tasklet_schedule(struct tasklet_struct *t) { diff -Nru a/kernel/suspend.c b/kernel/suspend.c --- a/kernel/suspend.c Sun Jun 2 18:44:56 2002 +++ b/kernel/suspend.c Sun Jun 2 18:44:56 2002 @@ -64,6 +64,7 @@ #include #include #include +#include unsigned char software_suspend_enabled = 0; @@ -300,7 +301,8 @@ static void do_suspend_sync(void) { while (1) { - run_task_queue(&tq_disk); + blk_run_queues(); +#error this is broken, FIXME if (!TQ_ACTIVE(tq_disk)) break; printk(KERN_ERR "Hm, tq_disk is not empty after run_task_queue\n"); @@ -326,7 +328,7 @@ if (!cur) panic("Out of memory in mark_swapfiles"); /* XXX: this is dirty hack to get first page of swap file */ - entry = SWP_ENTRY(root_swap, 0); + entry = swp_entry(root_swap, 0); lock_page(virt_to_page((unsigned long)cur)); rw_swap_page_nolock(READ, entry, (char *) cur); @@ -419,7 +421,7 @@ if (!(entry = get_swap_page()).val) panic("\nNot enough swapspace when writing data" ); - if(swapfile_used[SWP_TYPE(entry)] != SWAPFILE_SUSPEND) + if(swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND) panic("\nPage %d: not enough swapspace on suspend device", i ); address = (pagedir_nosave+i)->address; @@ -445,7 +447,7 @@ return -ENOSPC; } - if(swapfile_used[SWP_TYPE(entry)] != SWAPFILE_SUSPEND) + if(swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND) panic("\nNot enough swapspace for pagedir on suspend device" ); if (sizeof(swp_entry_t) != sizeof(long)) @@ -465,7 +467,7 @@ panic("union diskpage has bad size"); if (!(entry = get_swap_page()).val) panic( "\nNot enough swapspace when writing header" ); - if(swapfile_used[SWP_TYPE(entry)] != SWAPFILE_SUSPEND) + if(swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND) panic("\nNot enough swapspace for header on suspend device" ); cur = (void *) buffer; @@ -480,7 +482,7 @@ PRINTK( ", signature" ); #if 0 - if (SWP_TYPE(entry) != 0) + if (swp_type(entry) != 0) panic("Need just one swapfile"); #endif mark_swapfiles(prev, MARK_SWAP_SUSPEND); @@ -1068,7 +1070,7 @@ if (bdev_read_page(resume_device, pos, ptr)) { error = -EIO; goto resume_read_error; } #define PREPARENEXT \ { next = cur->link.next; \ - next.val = SWP_OFFSET(next) * PAGE_SIZE; \ + next.val = swp_offset(next) * PAGE_SIZE; \ } error = -EIO; @@ -1141,7 +1143,7 @@ swp_entry_t swap_address = (pagedir_nosave+i)->swap_address; if (!(i%100)) PRINTK( "." ); - next.val = SWP_OFFSET (swap_address) * PAGE_SIZE; + next.val = swp_offset(swap_address) * PAGE_SIZE; /* You do not need to check for overlaps... ... check_pagedir already did this work */ READTO(next.val, (char *)((pagedir_nosave+i)->address)); diff -Nru a/kernel/time.c b/kernel/time.c --- a/kernel/time.c Sun Jun 2 18:44:56 2002 +++ b/kernel/time.c Sun Jun 2 18:44:56 2002 @@ -39,6 +39,7 @@ /* The xtime_lock is not only serializing the xtime read/writes but it's also serializing all accesses to the global NTP variables now. */ extern rwlock_t xtime_lock; +extern unsigned long last_time_offset; #if !defined(__alpha__) && !defined(__ia64__) @@ -82,6 +83,7 @@ write_lock_irq(&xtime_lock); xtime.tv_sec = value; xtime.tv_usec = 0; + last_time_offset = 0; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; @@ -127,6 +129,7 @@ { write_lock_irq(&xtime_lock); xtime.tv_sec += sys_tz.tz_minuteswest * 60; + last_time_offset = 0; write_unlock_irq(&xtime_lock); } @@ -386,6 +389,7 @@ txc->calcnt = pps_calcnt; txc->errcnt = pps_errcnt; txc->stbcnt = pps_stbcnt; + last_time_offset = 0; write_unlock_irq(&xtime_lock); do_gettimeofday(&txc->time); return(result); diff -Nru a/kernel/timer.c b/kernel/timer.c --- a/kernel/timer.c Sun Jun 2 18:44:57 2002 +++ b/kernel/timer.c Sun Jun 2 18:44:57 2002 @@ -630,6 +630,7 @@ * This spinlock protect us from races in SMP while playing with xtime. -arca */ rwlock_t xtime_lock = RW_LOCK_UNLOCKED; +unsigned long last_time_offset; static inline void update_times(void) { @@ -647,6 +648,7 @@ wall_jiffies += ticks; update_wall_time(ticks); } + last_time_offset = 0; write_unlock_irq(&xtime_lock); calc_load(ticks); } diff -Nru a/kernel/user.c b/kernel/user.c --- a/kernel/user.c Sun Jun 2 18:44:57 2002 +++ b/kernel/user.c Sun Jun 2 18:44:57 2002 @@ -11,6 +11,7 @@ #include #include #include +#include /* * UID task count cache, to get fast user lookup in "alloc_uid" @@ -19,11 +20,11 @@ #define UIDHASH_BITS 8 #define UIDHASH_SZ (1 << UIDHASH_BITS) #define UIDHASH_MASK (UIDHASH_SZ - 1) -#define __uidhashfn(uid) (((uid >> UIDHASH_BITS) ^ uid) & UIDHASH_MASK) -#define uidhashentry(uid) (uidhash_table + __uidhashfn(uid)) +#define __uidhashfn(uid) (((uid >> UIDHASH_BITS) + uid) & UIDHASH_MASK) +#define uidhashentry(uid) (uidhash_table + __uidhashfn((uid))) static kmem_cache_t *uid_cachep; -static struct user_struct *uidhash_table[UIDHASH_SZ]; +static struct list_head uidhash_table[UIDHASH_SZ]; static spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED; struct user_struct root_user = { @@ -35,42 +36,32 @@ /* * These routines must be called with the uidhash spinlock held! */ -static inline void uid_hash_insert(struct user_struct *up, struct user_struct **hashent) +static inline void uid_hash_insert(struct user_struct *up, struct list_head *hashent) { - struct user_struct *next = *hashent; - - up->next = next; - if (next) - next->pprev = &up->next; - up->pprev = hashent; - *hashent = up; + list_add(&up->uidhash_list, hashent); } static inline void uid_hash_remove(struct user_struct *up) { - struct user_struct *next = up->next; - struct user_struct **pprev = up->pprev; - - if (next) - next->pprev = pprev; - *pprev = next; + list_del(&up->uidhash_list); } -static inline struct user_struct *uid_hash_find(uid_t uid, struct user_struct **hashent) +static inline struct user_struct *uid_hash_find(uid_t uid, struct list_head *hashent) { - struct user_struct *next; + struct list_head *up; + + list_for_each(up, hashent) { + struct user_struct *user; + + user = list_entry(up, struct user_struct, uidhash_list); - next = *hashent; - for (;;) { - struct user_struct *up = next; - if (next) { - next = up->next; - if (up->uid != uid) - continue; - atomic_inc(&up->__count); + if(user->uid == uid) { + atomic_inc(&user->__count); + return user; } - return up; } + + return NULL; } void free_uid(struct user_struct *up) @@ -84,7 +75,7 @@ struct user_struct * alloc_uid(uid_t uid) { - struct user_struct **hashent = uidhashentry(uid); + struct list_head *hashent = uidhashentry(uid); struct user_struct *up; spin_lock(&uidhash_lock); @@ -123,11 +114,16 @@ static int __init uid_cache_init(void) { + int n; + uid_cachep = kmem_cache_create("uid_cache", sizeof(struct user_struct), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if(!uid_cachep) panic("Cannot create uid taskcount SLAB cache\n"); + + for(n = 0; n < UIDHASH_SZ; ++n) + INIT_LIST_HEAD(uidhash_table + n); /* Insert the root user immediately - init already runs with this */ uid_hash_insert(&root_user, uidhashentry(0)); diff -Nru a/mm/filemap.c b/mm/filemap.c --- a/mm/filemap.c Sun Jun 2 18:44:57 2002 +++ b/mm/filemap.c Sun Jun 2 18:44:57 2002 @@ -23,7 +23,7 @@ /* * This is needed for the following functions: * - try_to_release_page - * - block_flushpage + * - block_invalidatepage * - page_has_buffers * - generic_osync_inode * @@ -53,7 +53,9 @@ * pagemap_lru_lock * ->i_shared_lock (vmtruncate) * ->private_lock (__free_pte->__set_page_dirty_buffers) - * ->mapping->page_lock + * ->swap_list_lock + * ->swap_device_lock (exclusive_swap_page, others) + * ->mapping->page_lock * ->inode_lock (__mark_inode_dirty) * ->sb_lock (fs/fs-writeback.c) */ @@ -152,30 +154,30 @@ spin_unlock(&pagemap_lru_lock); } -static int do_flushpage(struct page *page, unsigned long offset) +static int do_invalidatepage(struct page *page, unsigned long offset) { - int (*flushpage) (struct page *, unsigned long); - flushpage = page->mapping->a_ops->flushpage; - if (flushpage) - return (*flushpage)(page, offset); - return block_flushpage(page, offset); + int (*invalidatepage)(struct page *, unsigned long); + invalidatepage = page->mapping->a_ops->invalidatepage; + if (invalidatepage) + return (*invalidatepage)(page, offset); + return block_invalidatepage(page, offset); } static inline void truncate_partial_page(struct page *page, unsigned partial) { memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial); if (PagePrivate(page)) - do_flushpage(page, partial); + do_invalidatepage(page, partial); } /* * AKPM: the PagePrivate test here seems a bit bogus. It bypasses the - * mapping's ->flushpage, which may still want to be called. + * mapping's ->invalidatepage, which may still want to be called. */ static void truncate_complete_page(struct page *page) { /* Leave it on the LRU if it gets converted into anonymous buffers */ - if (!PagePrivate(page) || do_flushpage(page, 0)) + if (!PagePrivate(page) || do_invalidatepage(page, 0)) lru_cache_del(page); ClearPageDirty(page); ClearPageUptodate(page); @@ -337,7 +339,7 @@ page_cache_get(page); write_unlock(&mapping->page_lock); - block_flushpage(page, 0); + do_invalidatepage(page, 0); } else unlocked = 0; @@ -448,7 +450,7 @@ } /* Set the page dirty again, unlock */ - SetPageDirty(page); + set_page_dirty(page); unlock_page(page); return 0; } @@ -2098,6 +2100,7 @@ ssize_t written; int err; unsigned bytes; + time_t time_now; if (unlikely((ssize_t) count < 0)) return -EINVAL; @@ -2195,9 +2198,12 @@ goto out; remove_suid(file->f_dentry); - inode->i_ctime = CURRENT_TIME; - inode->i_mtime = CURRENT_TIME; - mark_inode_dirty_sync(inode); + time_now = CURRENT_TIME; + if (inode->i_ctime != time_now || inode->i_mtime != time_now) { + inode->i_ctime = time_now; + inode->i_mtime = time_now; + mark_inode_dirty_sync(inode); + } if (unlikely(file->f_flags & O_DIRECT)) { written = generic_file_direct_IO(WRITE, file, diff -Nru a/mm/memory.c b/mm/memory.c --- a/mm/memory.c Sun Jun 2 18:44:57 2002 +++ b/mm/memory.c Sun Jun 2 18:44:57 2002 @@ -50,6 +50,8 @@ #include #include +#include + unsigned long max_mapnr; unsigned long num_physpages; void * high_memory; @@ -1128,7 +1130,7 @@ num = valid_swaphandles(entry, &offset); for (i = 0; i < num; offset++, i++) { /* Ok, do the async read-ahead now */ - new_page = read_swap_cache_async(SWP_ENTRY(SWP_TYPE(entry), offset)); + new_page = read_swap_cache_async(swp_entry(swp_type(entry), offset)); if (!new_page) break; page_cache_release(new_page); diff -Nru a/mm/mmap.c b/mm/mmap.c --- a/mm/mmap.c Sun Jun 2 18:44:56 2002 +++ b/mm/mmap.c Sun Jun 2 18:44:56 2002 @@ -1124,7 +1124,7 @@ BUG(); clear_page_tables(tlb, FIRST_USER_PGD_NR, USER_PTRS_PER_PGD); - tlb_finish_mmu(tlb, FIRST_USER_PGD_NR*PGDIR_SIZE, USER_PTRS_PER_PGD*PGDIR_SIZE); + tlb_finish_mmu(tlb, 0, TASK_SIZE); mpnt = mm->mmap; mm->mmap = mm->mmap_cache = NULL; diff -Nru a/mm/page-writeback.c b/mm/page-writeback.c --- a/mm/page-writeback.c Sun Jun 2 18:44:56 2002 +++ b/mm/page-writeback.c Sun Jun 2 18:44:56 2002 @@ -497,7 +497,7 @@ spin_lock(&mapping->private_lock); - if (page_has_buffers(page) && !PageSwapCache(page)) { + if (page_has_buffers(page)) { struct buffer_head *head = page_buffers(page); struct buffer_head *bh = head; diff -Nru a/mm/shmem.c b/mm/shmem.c --- a/mm/shmem.c Sun Jun 2 18:44:57 2002 +++ b/mm/shmem.c Sun Jun 2 18:44:57 2002 @@ -52,6 +52,8 @@ static spinlock_t shmem_ilock = SPIN_LOCK_UNLOCKED; atomic_t shmem_nrpages = ATOMIC_INIT(0); /* Not used right now */ +static struct page *shmem_getpage_locked(struct shmem_inode_info *, struct inode *, unsigned long); + #define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512) /* @@ -317,6 +319,7 @@ static void shmem_truncate (struct inode * inode) { unsigned long index; + unsigned long partial; unsigned long freed = 0; struct shmem_inode_info * info = SHMEM_I(inode); @@ -324,6 +327,28 @@ inode->i_ctime = inode->i_mtime = CURRENT_TIME; spin_lock (&info->lock); index = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + partial = inode->i_size & ~PAGE_CACHE_MASK; + + if (partial) { + swp_entry_t *entry = shmem_swp_entry(info, index-1, 0); + struct page *page; + /* + * This check is racy: it's faintly possible that page + * was assigned to swap during truncate_inode_pages, + * and now assigned to file; but better than nothing. + */ + if (!IS_ERR(entry) && entry->val) { + spin_unlock(&info->lock); + page = shmem_getpage_locked(info, inode, index-1); + if (!IS_ERR(page)) { + memclear_highpage_flush(page, partial, + PAGE_CACHE_SIZE - partial); + unlock_page(page); + page_cache_release(page); + } + spin_lock(&info->lock); + } + } while (index < info->next_index) freed += shmem_truncate_indirect(info, index); @@ -369,10 +394,10 @@ swp_entry_t *ptr; unsigned long idx; int offset; + struct inode *inode = NULL; - spin_lock (&info->lock); -repeat: idx = 0; + spin_lock (&info->lock); offset = shmem_clear_swp (entry, info->i_direct, SHMEM_NR_DIRECT); if (offset >= 0) goto found; @@ -389,20 +414,36 @@ spin_unlock (&info->lock); return 0; found: - if (!move_from_swap_cache (page, offset+idx, info->vfs_inode.i_mapping)) { - info->swapped--; - SetPageUptodate (page); - spin_unlock (&info->lock); - return 1; + idx += offset; + inode = igrab(&info->vfs_inode); + spin_unlock(&shmem_ilock); + + while (inode && move_from_swap_cache(page, idx, inode->i_mapping)) { + /* + * Yield for kswapd, and try again - but we're still + * holding the page lock - ugh! fix this up later on. + * Beware of inode being unlinked or truncated: just + * leave try_to_unuse to delete_from_swap_cache if so. + */ + spin_unlock(&info->lock); + yield(); + spin_lock(&info->lock); + ptr = shmem_swp_entry(info, idx, 0); + if (IS_ERR(ptr)) + break; } - /* Yield for kswapd, and try again */ - yield(); - goto repeat; + info->swapped--; + SetPageUptodate(page); + spin_unlock(&info->lock); + if (inode) + iput(inode); + return 1; } /* - * unuse_shmem() search for an eventually swapped out shmem page. + * shmem_unuse() search for an eventually swapped out shmem page. + * Note shmem_unuse_inode drops shmem_ilock itself if successful. */ void shmem_unuse(swp_entry_t entry, struct page *page) { @@ -414,7 +455,7 @@ info = list_entry(p, struct shmem_inode_info, list); if (shmem_unuse_inode(info, entry, page)) - break; + return; } spin_unlock (&shmem_ilock); } @@ -551,6 +592,7 @@ error = move_from_swap_cache(page, idx, mapping); if (error < 0) { unlock_page(page); + page_cache_release(page); return ERR_PTR(error); } @@ -576,11 +618,11 @@ * is enough to make this atomic. */ page = page_cache_alloc(mapping); if (!page) - return ERR_PTR(-ENOMEM); + goto no_mem; error = add_to_page_cache(page, mapping, idx); if (error < 0) { page_cache_release(page); - return ERR_PTR(-ENOMEM); + goto no_mem; } clear_highpage(page); inode->i_blocks += BLOCKS_PER_PAGE; @@ -589,6 +631,13 @@ /* We have the page */ SetPageUptodate(page); return page; + +no_mem: + spin_lock(&sbinfo->stat_lock); + sbinfo->free_blocks++; + spin_unlock(&sbinfo->stat_lock); + return ERR_PTR(-ENOMEM); + no_space: spin_unlock (&sbinfo->stat_lock); return ERR_PTR(-ENOSPC); @@ -854,7 +903,7 @@ flush_dcache_page(page); if (bytes > 0) { - SetPageDirty(page); + set_page_dirty(page); written += bytes; count -= bytes; pos += bytes; @@ -1139,7 +1188,7 @@ kaddr = kmap(page); memcpy(kaddr, symname, len); kunmap(page); - SetPageDirty(page); + set_page_dirty(page); unlock_page(page); page_cache_release(page); up(&info->sem); @@ -1396,6 +1445,7 @@ static struct address_space_operations shmem_aops = { writepage: shmem_writepage, + set_page_dirty: __set_page_dirty_nobuffers, }; static struct file_operations shmem_file_operations = { diff -Nru a/mm/swap_state.c b/mm/swap_state.c --- a/mm/swap_state.c Sun Jun 2 18:44:57 2002 +++ b/mm/swap_state.c Sun Jun 2 18:44:57 2002 @@ -14,7 +14,7 @@ #include #include #include -#include /* for block_sync_page()/block_flushpage() */ +#include /* block_sync_page()/try_to_free_buffers() */ #include @@ -48,9 +48,10 @@ } static struct address_space_operations swap_aops = { - vm_writeback: swap_vm_writeback, - writepage: swap_writepage, - sync_page: block_sync_page, + vm_writeback: swap_vm_writeback, + writepage: swap_writepage, + sync_page: block_sync_page, + set_page_dirty: __set_page_dirty_nobuffers, }; /* @@ -149,11 +150,15 @@ { swp_entry_t entry; - if (!PageLocked(page)) + /* + * I/O should have completed and nobody can have a ref against the + * page's buffers + */ + BUG_ON(!PageLocked(page)); + BUG_ON(PageWriteback(page)); + if (page_has_buffers(page) && !try_to_free_buffers(page)) BUG(); - - block_flushpage(page, 0); - + entry.val = page->index; write_lock(&swapper_space.page_lock); @@ -218,7 +223,15 @@ void **pslot; int err; - if (!PageLocked(page)) + /* + * Drop the buffers now, before taking the page_lock. Because + * mapping->private_lock nests outside mapping->page_lock. + * This "must" succeed. The page is locked and all I/O has completed + * and nobody else has a ref against its buffers. + */ + BUG_ON(!PageLocked(page)); + BUG_ON(PageWriteback(page)); + if (page_has_buffers(page) && !try_to_free_buffers(page)) BUG(); write_lock(&swapper_space.page_lock); @@ -228,10 +241,8 @@ if (!err) { swp_entry_t entry; - block_flushpage(page, 0); entry.val = page->index; __delete_from_swap_cache(page); - swap_free(entry); *pslot = page; page->flags &= ~(1 << PG_uptodate | 1 << PG_error | @@ -247,11 +258,16 @@ /* fix that up */ list_del(&page->list); list_add(&page->list, &mapping->dirty_pages); + write_unlock(&mapping->page_lock); + write_unlock(&swapper_space.page_lock); + + /* Do this outside ->page_lock */ + swap_free(entry); + return 0; } write_unlock(&mapping->page_lock); write_unlock(&swapper_space.page_lock); - return err; } diff -Nru a/mm/swapfile.c b/mm/swapfile.c --- a/mm/swapfile.c Sun Jun 2 18:44:56 2002 +++ b/mm/swapfile.c Sun Jun 2 18:44:56 2002 @@ -16,9 +16,10 @@ #include #include #include -#include /* for block_flushpage() */ +#include /* for try_to_free_buffers() */ #include +#include spinlock_t swaplock = SPIN_LOCK_UNLOCKED; unsigned int nr_swapfiles; @@ -121,7 +122,7 @@ offset = scan_swap_map(p); swap_device_unlock(p); if (offset) { - entry = SWP_ENTRY(type,offset); + entry = swp_entry(type,offset); type = swap_info[type].next; if (type < 0 || p->prio != swap_info[type].prio) { @@ -154,13 +155,13 @@ if (!entry.val) goto out; - type = SWP_TYPE(entry); + type = swp_type(entry); if (type >= nr_swapfiles) goto bad_nofile; p = & swap_info[type]; if (!(p->flags & SWP_USED)) goto bad_device; - offset = SWP_OFFSET(entry); + offset = swp_offset(entry); if (offset >= p->max) goto bad_offset; if (!p->swap_map[offset]) @@ -220,7 +221,7 @@ p = swap_info_get(entry); if (p) { - swap_entry_free(p, SWP_OFFSET(entry)); + swap_entry_free(p, swp_offset(entry)); swap_info_put(p); } } @@ -239,7 +240,7 @@ p = swap_info_get(entry); if (p) { /* Is the only swap cache user the cache itself? */ - if (p->swap_map[SWP_OFFSET(entry)] == 1) { + if (p->swap_map[swp_offset(entry)] == 1) { /* Recheck the page count with the pagecache lock held.. */ read_lock(&swapper_space.page_lock); if (page_count(page) - !!PagePrivate(page) == 2) @@ -307,7 +308,7 @@ /* Is the only swap cache user the cache itself? */ retval = 0; - if (p->swap_map[SWP_OFFSET(entry)] == 1) { + if (p->swap_map[swp_offset(entry)] == 1) { /* Recheck the page count with the pagecache lock held.. */ write_lock(&swapper_space.page_lock); if (page_count(page) - !!PagePrivate(page) == 2) { @@ -325,7 +326,9 @@ swap_info_put(p); if (retval) { - block_flushpage(page, 0); + BUG_ON(PageWriteback(page)); + if (page_has_buffers(page) && !try_to_free_buffers(page)) + BUG(); swap_free(entry); page_cache_release(page); } @@ -344,7 +347,7 @@ p = swap_info_get(entry); if (p) { - if (swap_entry_free(p, SWP_OFFSET(entry)) == 1) + if (swap_entry_free(p, swp_offset(entry)) == 1) page = find_trylock_page(&swapper_space, entry.val); swap_info_put(p); } @@ -568,7 +571,7 @@ * page and read the swap into it. */ swap_map = &si->swap_map[i]; - entry = SWP_ENTRY(type, i); + entry = swp_entry(type, i); page = read_swap_cache_async(entry); if (!page) { /* @@ -954,7 +957,7 @@ } lock_page(virt_to_page(swap_header)); - rw_swap_page_nolock(READ, SWP_ENTRY(type,0), (char *) swap_header); + rw_swap_page_nolock(READ, swp_entry(type,0), (char *) swap_header); if (!memcmp("SWAP-SPACE",swap_header->magic.magic,10)) swap_header_version = 1; @@ -1007,7 +1010,7 @@ } p->lowest_bit = 1; - maxpages = SWP_OFFSET(SWP_ENTRY(0,~0UL)) - 1; + maxpages = swp_offset(swp_entry(0,~0UL)) - 1; if (maxpages > swap_header->info.last_page) maxpages = swap_header->info.last_page; p->highest_bit = maxpages - 1; @@ -1141,11 +1144,11 @@ unsigned long offset, type; int result = 0; - type = SWP_TYPE(entry); + type = swp_type(entry); if (type >= nr_swapfiles) goto bad_file; p = type + swap_info; - offset = SWP_OFFSET(entry); + offset = swp_offset(entry); swap_device_lock(p); if (offset < p->max && p->swap_map[offset]) { @@ -1182,11 +1185,11 @@ entry.val = page->index; if (!entry.val) goto bad_entry; - type = SWP_TYPE(entry); + type = swp_type(entry); if (type >= nr_swapfiles) goto bad_file; p = type + swap_info; - offset = SWP_OFFSET(entry); + offset = swp_offset(entry); if (offset >= p->max) goto bad_offset; if (!p->swap_map[offset]) @@ -1218,14 +1221,14 @@ unsigned long type; struct swap_info_struct *p; - type = SWP_TYPE(entry); + type = swp_type(entry); if (type >= nr_swapfiles) { printk(KERN_ERR "rw_swap_page: %s%08lx\n", Bad_file, entry.val); return; } p = &swap_info[type]; - *offset = SWP_OFFSET(entry); + *offset = swp_offset(entry); if (*offset >= p->max && *offset != 0) { printk(KERN_ERR "rw_swap_page: %s%08lx\n", Bad_offset, entry.val); return; @@ -1250,11 +1253,11 @@ { int ret = 0, i = 1 << page_cluster; unsigned long toff; - struct swap_info_struct *swapdev = SWP_TYPE(entry) + swap_info; + struct swap_info_struct *swapdev = swp_type(entry) + swap_info; if (!page_cluster) /* no readahead */ return 0; - toff = (SWP_OFFSET(entry) >> page_cluster) << page_cluster; + toff = (swp_offset(entry) >> page_cluster) << page_cluster; if (!toff) /* first page is swap header */ toff++, i--; *offset = toff; diff -Nru a/mm/vmscan.c b/mm/vmscan.c --- a/mm/vmscan.c Sun Jun 2 18:44:56 2002 +++ b/mm/vmscan.c Sun Jun 2 18:44:56 2002 @@ -27,6 +27,7 @@ #include #include +#include /* * The "priority" of VM scanning is how much of the queues we diff -Nru a/scripts/mkdep.c b/scripts/mkdep.c --- a/scripts/mkdep.c Sun Jun 2 18:44:57 2002 +++ b/scripts/mkdep.c Sun Jun 2 18:44:57 2002 @@ -267,7 +267,7 @@ pc += 7; for (i = 0; i < len; i++) { - char c = name[i]; + int c = (unsigned char) name[i]; if (isupper(c)) c = tolower(c); if (c == '_') c = '/'; pc[i] = c; diff -Nru a/scripts/split-include.c b/scripts/split-include.c --- a/scripts/split-include.c Sun Jun 2 18:44:57 2002 +++ b/scripts/split-include.c Sun Jun 2 18:44:57 2002 @@ -117,7 +117,7 @@ str_config += sizeof("CONFIG_") - 1; for (itarget = 0; !isspace(str_config[itarget]); itarget++) { - char c = str_config[itarget]; + int c = (unsigned char) str_config[itarget]; if (isupper(c)) c = tolower(c); if (c == '_') c = '/'; ptarget[itarget] = c; diff -Nru a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c --- a/sound/isa/sb/sb16_csp.c Sun Jun 2 18:44:57 2002 +++ b/sound/isa/sb/sb16_csp.c Sun Jun 2 18:44:57 2002 @@ -215,7 +215,7 @@ info.run_width = p->run_width; info.version = p->version; info.state = p->running; - err = copy_to_user((void *) arg, &info, sizeof(info)); + err = copy_to_user((void *) arg, &info, sizeof(info)) ? -EFAULT : 0; break; /* load CSP microcode */